如何使用read()函数读取文件直到文件结束?

12

我正在尝试使用read()在C程序中读取二进制数据,但EOF测试不起作用。相反,它一直运行,读取文件的最后一个比特。

#include <stdio.h>
#include <fcntl.h>
int main() {

  // writing binary numbers to a file
  int fd = open("afile", O_WRONLY | O_CREAT, 0644);
  int i;
  for (i = 0; i < 10; i++) {
    write(fd, &i, sizeof(int));
  }
  close(fd);

  //trying to read them until EOF
  fd = open("afile", O_RDONLY, 0);
  while (read(fd, &i, sizeof(int)) != EOF) {
    printf("%d", i);
  }
  close(fd);
}

2
不是立即的问题(读取返回0,而不是EOF),但你可能应该养成使用gcc -Wall编译的习惯,注意警告(并修复它们!),在使用read/write时要包含<unistd.h> - Paul R
谢谢你的建议,我已经在需要的主要代码中包含了它,但从现在开始也会使用-Wall :) - sekmet64
3个回答

25

read返回读取的字符数。当它到达文件结尾时,它将无法再读取任何内容,并返回0而不是EOF。


哎呀:S 不知道我怎么在手册中漏掉了那个,过去20分钟一直在阅读相关内容。 - sekmet64
2
我能理解为什么这不是显而易见的。毕竟,人们可以想到很多原因为什么可能读取0字节。关键在于,当read遇到错误时,它总是返回-1,而从不返回0。返回0表示成功,文件结束。据我所知,即使对于非阻塞IO,在那里它是可能的,并且有时非常可能读取0字节,只有在达到EOF时才会返回0。其余时间,在没有要读取的字节且未达到EOF时,将返回-1并且errno = EAGAIN。至少,这是我的理解。 - enigmaticPhysicist

3
你必须检查错误。在一些常见的错误情况下,你需要再次调用read()函数!
如果read()函数返回-1,那么你需要检查errno错误码。如果errno等于EAGAIN或EINTR,则需要重新启动read()函数调用,而不使用其(不完整的)返回值。(在其他错误情况下,你可能需要使用strerror函数输出适当的错误信息并退出程序)
示例:git源代码中的一个称为xread()的包装器。链接:http://repo.or.cz/w/git.git/blob/HEAD:/wrapper.c#l126

0

POSIX rasys 返回值为 0 表示文件结束

http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html

如果没有进程打开管道进行写入,则read()将返回0以指示文件结尾。
这证实了{{link1:Jerry的答案}}。
一些ANSI函数返回 EOF ,例如 man getc 中所述:
fgetc(),getc()和getchar()将读取的字符作为无符号字符强制转换为int或EOF返回文件结束或错误。 ungetc()在成功时返回c,或在错误时返回EOF。
因此,在这种情况下,仍然无法使用它来区分错误和文件结束,需要使用 feof 。
另请参阅:{{link2:如何在C中使用EOF运行文本文件?}}

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