- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在一个非常大的文件中运行 fseek(..)
时性能很差。每次调用fseek
函数,我需要将文件指针位置向后移动100字节
:
fseek(fp, -100, SEEK_CUR);
之前,我是这样做的:
fseek(fp, (index)*100, SEEK_SET); // which makes basically the same...
我的问题是 fseek 如何在文件中移动指针并将文件指针设置在特定位置。
我以为它获取文件指针并将其向后移动,但现在我认为它真正做的是
获取当前位置(cp
)
添加负索引(p = idx + cp
)
并将文件指针从文件开头移动到该位置 (fseek(fp, p, SEEK_SET)
)
最佳答案
首先,您使用的是什么操作系统?如果是 Linux,请在 strace
下运行您的应用程序以查看它实际进行的系统调用。
其次,fopen()/fseek()/fread()
是这种访问模式的错误工具。这些调用缓冲文件读取 - 通过读取提前。那对你没有好处。你 fseek()
偏移 X,无论缓冲的数据现在是无用的,你 fread()
100 字节,缓冲的 fread()
阅读更多 - 大概 8 kB。您可能会读取文件的几乎每个字节超过 80 次。您可以使用 setbuf()
或 setvbuf()
来禁用缓冲,但是您将在向后浏览文件时进行 100 字节的读取。它应该更快,但不会快到你能走的那么快。
尽可能快地执行此操作(无需进入多线程和/或异步 IO):
使用open()/pread()
。您不需要寻找 - pread()
直接从任意偏移量读取。
读取更大的 block - 比如 8192 x 100。或者更大。像以前一样向后读取,但自己进行缓冲并从文件中的偏移量开始,该偏移量是您正在读取的大尺寸的倍数 - 第一次读取可能会少于 819,200 字节。首先处理缓冲区中的最后 100 个字节,然后向后处理缓冲区。处理完缓冲区中的前 100 个字节后,使用 pread()
从文件中读取之前的 819,200 个字节(或更大)。
如果可用,请使用直接 IO。文件系统优化可能会尝试通过读取提前 并将数据放入页面缓存(您已经处理过的数据)来“优化”您的访问。因此,如果可能,请绕过页面缓存(并非所有操作系统都支持直接 IO,也并非所有支持直接 IO 的操作系统上的文件系统都实现它。)
像这样:
#define DATA_SIZE 100
#define NUM_CHUNKS (32UL * 1024UL)
#define READ_SIZE ( ( size_t ) DATA_SIZE * NUM_CHUNKS )
void processBuffer( const char *buffer, ssize_t bytes )
{
if ( bytes <= 0 ) return;
// process a buffer backwards...
}
void processFile( const char *filename )
{
struct stat sb;
// get page-aligned buffer for direct IO
char *buffer = valloc( READ_SIZE );
// Linux-style direct IO
int fd = open( filename, O_RDONLY | O_DIRECT );
fstat( fd, &sb );
// how many read operations?
// use lldiv() to get quotient and remainder in one op
lldiv_t numReads = lldiv( sb.st_size, READ_SIZE );
if ( numReads.rem )
{
numReads.quot++;
}
while ( numReads.quot > 0 )
{
numReads.quot--;
ssize_t bytesRead = pread( fd, buffer,
READ_SIZE, numReads.quot * READ_SIZE );
processBuffer( buffer, bytesRead );
}
free( buffer );
close( fd );
}
您需要为其添加错误处理。
关于c - fseek 传递负偏移量和 SEEK_CUR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32015916/
offset=ftell(ptr)-sizeof(student1); fseek(ptr,offset,SEEK_SET); fwrite(&student1,sizeof(student1),1,
我在一个非常大的文件中运行 fseek(..) 时性能很差。每次调用fseek函数,我需要将文件指针位置向后移动100字节: fseek(fp, -100, SEEK_CUR); 之前,我是这样做
#include main () { FILE *fs, *ft; char dest[20]; fs = fopen ("STACKOVERFLOW.txt", "r"); fsee
据推测,这一行应该没有效果;从当前位置开始寻找 0 个字节。但是,我在一些遗留代码中找到了这一行,如果没有这一行,似乎没有任何效果——即使在 python 中,使用等效的 fp.seek(0, os.
fwrite() 会完成 fseek(f,1,SEEK_CUR) 的工作吗? 我的代码是: while (fread(&tmp,sizeof(compt),1,fc)) {
我已经测试了以下 C 代码 #include int main() { FILE * file = fopen("ans.txt", "r+"); printf("%ld", fte
这两者有什么区别吗? 答: # seek back by difference from current position fp.seek(last_read_byte - fp.tell(), os
难道我们不应该为 whence 使用 SEEK_CUR/SEEK_SET 或 SEEK_END 吗?它如何只使用固定值? 最佳答案 SEEK_SET/SEEK_CUR/SEEK_END分别为0/1/2
我从来没有意识到这一点。我本可以下意识地假设一个硬事实,即我可以在现有文件上的读写之间转换,打开它更新模式,就像那样。但是关于 SO 的两个问题(1 , 2 ) 让我怀疑,我决定尝试一下。这是我的发现
我是一名优秀的程序员,十分优秀!