神奇好望角 The Magical Cape of Good Hope

庸人不必自扰,智者何需千虑?
posts - 26, comments - 50, trackbacks - 0, articles - 11
  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理
C 库函数 feof(FILE*) 判断文件末尾的问题 A Problem on Using C Library Function feof(FILE*) to Judge The End of A File
  我用 C 写了一个程序读取 32768 字节大小的文件,每次读 16 个字节,应该是 2048 次读完。但结果读了 2049 次,并且最后两次的数据相同,似乎重复读取了最后 16 个字节。源代码如下:     I wrote a program with C, which read a file of 32768 bytes, 16 bytes each time, and it should finish reading after 2048 times. But the reault was it read 2049 times, and the data of last two times are the same, which seemed the last 16 bytes were read twice. Here is the code:
  1. int loop = 0;
  2. while (!feof(file)) {
  3.     loop++;
  4.     fread(buffer, 16, 1, file);
  5.     ......
  6. }
  7. printf("%d\n", loop);    // 2049
  我看了一阵,发现导致这个错误的原因是 feof(FILE*) 判断文件末尾的机制:文件指针在文件末尾的时候,除非再读一次导致发生 I/O 错误,feof(FILE*) 依然返回 0。因此用 feof(FILE*) 作为判断条件的 while 循环始终会多读一次,而最后一次的读取是失败的,buffer 也就没有改变,看起来就像是重复读了一次。     I reviewed it for a whil and found the reason that produced this error is the mechanism feof(FILE*) used to judge the end of a file: When the file pointer is at the end of a file, feof(FILE*) still returns 0 unless reads one more time to course a I/O error. Therefore, a while loop using feof(FILE*) as the judgment condition always reads one more time, and the last time of reading will fail, so buffer stayed unchanged which looked like it repeated reading once.
  用下面的代码就没问题了:     Use the code below to solve this problem:
  1. int loop = 0;
  2. while (fread(buffer, 16, 1, file) == 1) {
  3.     loop++;
  4.     ......
  5. }
  6. printf("%d\n", loop); // 2048

评论

# 关于feof(FILE*)  回复  更多评论   

2008-11-03 19:33 by friend
其实可以在循环体内加上一句:
if(feof(file))break;
我估计就行了。

# re: C 库函数 feof(FILE*) 判断文件末尾的问题[未登录]  回复  更多评论   

2014-10-31 17:52 by barry
上面结论是对的,但下面的代码也是有问题的,

int loop = 0;
while (fread(buffer, 16, 1, file) == 1) {
loop++;
......
}
printf("%d\n", loop); // 2048

应该改成:
int loop = 0;
while (fread(buffer, 16, 1, file) !=1) {
loop++;
......
}
printf("%d\n", loop); // 2048

if(feof(file)==EOF)
....
if(ferror(file))
....

# re: C 库函数 feof(FILE*) 判断文件末尾的问题[未登录]  回复  更多评论   

2014-10-31 17:59 by barry
@barry

sorry,

while (fread(buffer, 16, 1, file) !=1
应该还是
while (fread(buffer, 16, 1, file) ==1
只是最后结束循环次数未必一定是2048

因为即使等于1,也可能是出错的情况之一,这时候循环不会停止。
如果要求出错马上退出,只能在循环中判断。

# re: C 库函数 feof(FILE*) 判断文件末尾的问题[未登录]  回复  更多评论   

2014-10-31 18:28 by barry
尤其是块数是N,而不是1的情况下,这样写更有意义
while (fread(buffer, 16, N, file) ==N

最后结束的时候,返回的块数大多数情况下会小于N,这个时候,也有可能是因为出错,没有读完N就出来了,或者到文件尾,剩下的块小于N,也跑出来。

后面要检测不同结果,因为最终循环结束,未必是文件读完了。

只有注册用户登录后才能发表评论。


网站导航: