在C中使用fseek比使用fread序列有什么优势

  • 本文关键字:fread fseek c file stream fseek
  • 更新时间 :
  • 英文 :


我是C编程的初学者,我对如何处理文件有一些问题。

假设我们有一个存储了N个int值的二进制文件。让我们假设我们要读取文件中的第i个值。

使用fseek来定位指向第i个int值的文件指针并在fseek之后读取它,而不是使用一系列i fread调用,这有什么真正的优势吗?

直觉上,我认为fseek更快。但是函数如何在不读取中间信息的情况下找到文件中的第i个值呢?

我认为这取决于执行情况。因此,我试图找到fseek函数的实现,但没有取得多大成功。

但是函数如何在不读取中间信息的情况下找到文件中的第i个值?

没有。由您提供正确的(绝对或相对)偏移。例如,您可以请求将文件指针提前i*sizeof(X)

它仍然需要遵循文件所在的扇区链来找到正确的扇区,但这不需要读取这些扇区。该元数据存储在文件本身之外。

使用fseek将文件指针定位到第i个int值并在fseek之后读取它,而不是使用一系列i fread调用,这有什么真正的优势吗?

每个级别都有潜在的好处。

通过查找,系统可能不得不从磁盘读取更少的数据。系统在扇区中从磁盘读取,因此由于缓存的原因,短寻道可能没有这种好处。但是,对整个扇区进行查找会减少需要从磁盘中提取的数据量。

类似地,通过查找stdio库,我必须减少对操作系统的请求。stdio库的读取量通常超过所需量,因此将来对fread的调用不需要接触操作系统或磁盘。短寻道可能不需要进行任何系统调用,但在缓冲数据结束后进行寻道可以减少从操作系统获取的数据总量。

最后,在使用fseek时,跳过的数据根本不需要从stdio库的缓冲区复制到用户的缓冲区,无论您搜索多远。

哦,我们不要忘记,您正在考虑i-1读取,而不仅仅是一个大读取。这些读取中的每一个都消耗CPU,无论是在库中(错误检查)还是在调用方中(错误处理)。

使用fseek将文件指针定位到第i个int值并在fseek之后读取它,而不是使用一系列i fread调用,这有什么真正的优势吗

是的,如果您想从文件中读取一个值,并且您知道它在哪里,那么就没有理由读取其他值。

直觉上,我认为fseek更快。但是函数如何在不读取中间信息的情况下找到文件中的第i个值呢

你的直觉是正确的,如果你读一个值,那么它将比读几个值更有效率。它查找值的方法很简单,通常来说,文件中的每个位置都对应于1个字节,如果您传递偏移量,例如7,则下一次读取将从第8个字节开始,假设您的文件具有以下数据:

-58 10 12  14 7 9
^      ^
|      |
0      offset of 7
fseek(fp, 7, SEEK_SET);
if(fscanf(fp,"%d",&num) == 1 ){  
printf("%d", num);
}  

将输出12

文件指示器设置在第7个位置,然后从下一个字节开始读取。就好像你有一个数组,你想访问第7个位置,你只需要使用arr[7]

我认为这取决于实现

尽管可以定义一些小细节,但总体行为是标准化的。

§7.21.9.2 fseek函数

简介

1.

#include <stdio.h>
int fseek(FILE *stream, long int offset, int whence);

描述:

  1. fseek函数为流指向的流设置文件位置指示符。如果发生读取或写入错误,则会设置流的错误指示器,fseek将失败。

  2. 对于二进制流,从文件开始以字符为单位测量的新位置是通过将偏移量添加到由where指定的位置来获得的。如果其中是SEEK_SET,则指定的位置是文件的开头;如果是SEEK_CUR,则指定文件位置指示符的当前值;如果是SEEK_end,则指定位置是文件结尾。二进制流不需要有意义地支持where值为SEEK_END的fseek调用。

  3. 对于文本流,偏移量应为零,或者偏移量应为由先前成功调用与同一文件相关联的流上的ftell函数返回的值,其中应为SEEK_SET。

  4. 在确定新位置后,对fseek函数的成功调用将取消ungetc函数对流的任何影响,清除流的文件结尾指示符,然后建立新位置。在成功的fseek调用之后,对更新流的下一个操作可能是输入或输出。

退货:

  1. fseek函数仅对无法满足的请求返回非零