gpt4 book ai didi

c - fseek 传递负偏移量和 SEEK_CUR

转载 作者:太空狗 更新时间:2023-10-29 14:58:46 26 4
gpt4 key购买 nike

我在一个非常大的文件中运行 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):

  1. 使用open()/pread()。您不需要寻找 - pread() 直接从任意偏移量读取。

  2. 读取更大的 block - 比如 8192 x 100。或者更大。像以前一样向后读取,但自己进行缓冲并从文件中的偏移量开始,该偏移量是您正在读取的大尺寸的倍数 - 第一次读取可能会少于 819,200 字节。首先处理缓冲区中的最后 100 个字节,然后向后处理缓冲区。处理完缓冲区中的前 100 个字节后,使用 pread() 从文件中读取之前的 819,200 个字节(或更大)。

  3. 如果可用,请使用直接 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com