#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
struct stat sb;
/* Upon successful completion, 0 shall be returned.
* Otherwise, -1 shall be returned and
* errno set to indicate the error
*/
if (fstat(fd, &sb) == -1) {
perror ("fstat()");
/* Handle error here */
}
off_t size = buf.st_size;
调用lseek()以获取当前位置。 但正如评论中指出的:
“无论系统调用的次数有多少,这基本上都是不可能的,因为无论测试在某个时刻告诉你位置是否在文件末尾,下一个时刻另一个进程都可能截断或扩展文件。在获得结果之后,没有任何结果是可靠的。”* - Eric Postpischil
2条答案
按热度按时间3pmvbmvn1#
您只需 * 一次 * 系统调用即可测试文件结束:一个
read
!如果它返回0,你就在文件末尾。如果它不返回,你就不在文件末尾。...当然,如果它返回的值大于0,那么您就不在原来的位置,因此这可能不是一个好的解决方案,但是如果您的主要任务是读取文件,那么您刚刚通过
read
调用读取的数据很可能就是您想要的数据。你在一条评论中说,仅仅调用
read
的代码可能会"错综复杂,产生更难处理的代码",我"有点"明白你的意思。我依稀记得,在我的职业生涯中,有一两次,我希望我能知道下一个read
是否会成功,在我不得不这样做之前。但那只是一两次。巨大的,绝大多数时候,至少对我来说,只读一直读直到一个读调用返回0的代码是非常自然和直接的。增编:
K&R中的一些伪代码一直让我印象深刻,它们是
grep
的基本版本,在前面的一章中作为示例介绍的:这是针对基于行的输入,但更一般的模式
具有相同的优点,并且充实到实际的
read
调用并不涉及太大的更改:起初,嵌入的读取和测试(即对
n
的赋值和对0
的测试,隐藏在while
循环的单个控制表达式中)确实让我感到困扰,看起来似乎没有必要那么神秘,但它确实相当完美地封装了"while there's input/process it"(当有输入/处理它)的习惯用法,或者至少,给定一个C/Unix风格的读取调用,它只能在调用它的 * 之后指示EOF *。(This与Pascal风格的I/O相反,Pascal风格的I/O在你调用它之前 * 确实 * 表示EOF,并且是,或者曾经是,导致Why is
while( !feof(file) )
always wrong?成为规范SO问题的所有问题的主要动机。Brian Kernighan有一个描述,可能在 * 为什么Pascal不是我最喜欢的编程语言 * 中,实现一个Pascal风格的输入方法,在EOF发生之前显式地指出它是多么的困难和不自然。)hc2pp10m2#
如果你有一个文件描述符,你可以使用
fstat()
来获得文件的大小:调用
lseek()
以获取当前位置。但正如评论中指出的: