为什么在使用fread()函数后,ftell()函数显示的位置不正确?

7
我在尝试使用c fread()调用读取简单文本文件时遇到了一个非常奇怪的错误。我制作了一个非常简单的程序来展示这个错误:
int main(int argc ,char ** argv) {
  FILE* fh = fopen("adult.txt","r");
  if(fh==NULL){
    printf("error opening file\n");
    exit(0);
  }

  int s = 1000;
  printf("cur before=%d\n",ftell(fh));
  char* b = malloc (sizeof(char)*s);
  int k =fread(b,sizeof(char),s,fh);
  printf("cur after reading %d bytes =%d\n",k,ftell(fh));

  return EXIT_SUCCESS;
}

我得到的输出结果:

cur before=0
cur after reading 1000 bytes =1007

这正常吗?fread返回数字“1000”,但光标(使用ftell())显示1007,任何帮助将不胜感激。

3个回答

12

这很正常。

'\n' 可以用两个字符来表示,所以你会得到偏移结果。

如果你不想发生这种情况,以二进制模式打开文件即可。


谢谢,我不知道这个。但是我不明白为什么fread()的返回值和光标位置不一样? - ezzakrem
1
@ezzakrem 因为 fread 会将行尾(可能是两个字符)解释为一个字符,并将其报告为一个字符。 - Šimon Tóth

6
根据ftell的文档:
对于二进制流,返回值对应文件开头的字节数。对于文本流,返回值不能保证是文件开头的确切字节数,但依然可以使用返回的值通过fseek将位置指针恢复到该位置。
因此,这是正常的情况。

1
Let_Me_Be的回答是正确的。我在这里只是解释一下,“行尾”(EOL)字符取决于底层操作系统。例如,在Windows中,如果您使用“r”(或非二进制)打开文件,则每当出现“\r\n”序列时,操作系统将仅返回“\n”。同样,在未以二进制模式打开的文件中写入时,Windows将在您简单地写入“\n”时写入“\r\n”。对于Unix系统,操作系统不会进行此类翻译。经典的Mac电脑会使用“\r”作为行尾字符,但我认为现在它们使用“\n”作为EOL。我希望这能澄清“\n”可能由多个字符(\r\n)表示的流行用语。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接