为什么::feof()不同于::_eof(::fileno())



免责声明:不要使用::feof()作为循环条件例如,对于二进制文件,请参阅:file reading:feof()的答案

然而,我有"真实"的代码来演示一个问题,该问题不使用::feof()作为循环条件,但从逻辑上讲,这是演示该问题的最简单方法。

考虑以下内容:我们一次迭代一个字符流:

FILE* my_file;
// ...open "my_file" for reading...
int c;
while(0 == ::feof(my_file))
{ // We are not at EOF
  c = ::getc(my_file);
  // ...process "c"
}

以上代码按预期工作:文件一次处理一个字符,在EOF时退出。

但是,以下有意外行为

FILE* my_file;
// ...open "my_file" for reading...
int c;
while(0 == ::_eof(::fileno(my_file)))
{ // We are not at EOF
  c = ::getc(my_file);
  // ...process "c"
}

我本以为他们也会有同样的表现。::fileno()每次都正确地返回(整数)文件描述符。然而,测试::_eof(::fileno(my_file))只运行一次,然后在第二次尝试时返回1(指示EOF)。

我不明白。

我想可以想象,::feof()是"缓冲的"(因此它可以正常工作),而::_eof()是"未缓冲的",并且认为整个文件已经"读入"了(因为整个文件将适合从磁盘读入的第一个块)。然而,考虑到这些函数的目的,这不可能是真的。所以,我真的不知所措。

怎么回事?

(文件以"文本"打开,是大约有十几行的ASCII文本文件,MSVS2008,Win7/64。)

我想可以想象::feof()是"缓冲的"(所以它有效正确),而:_eof()是"未缓冲的",并认为整个文件已经"读入"了(因为整个文件本来可以放入从磁盘读取的第一块)。然而,这不可能是真的鉴于这些职能的目的。所以,我真的不知所措。

我不知道为什么你会认为"考虑到这些函数的目的,这不可能是真的"。这两个函数旨在对以不同方式打开和操作的文件进行操作,因此它们不兼容。

事实上,这正是正在发生的事情。试试这个:

FILE* my_file;
// ...open "my_file" for reading...
int c;
while(0 == ::_eof(::fileno(my_file)))
{ // We are not at EOF
  c = ::getc(my_file);
  long offset1 = ftell(my_file);
  long offset2 = _tell(fileno(my_file));
  if (offset1 != offset2)
  {
     //here you will see that the file pointers are different
     //which means that _eof and feof will fire true under different conditions
  }
  // ...process "c"
}

我将根据你的评论详细阐述一下。

当您调用fopen时,您将返回一个指向文件流的指针。底层流对象保留其自己的文件指针,该文件指针与与底层文件描述符相关联的实际文件指针分离。

当您调用_eof时,您会询问是否已到达实际文件的末尾。当您调用feof时,您会询问是否已到达文件的末尾。由于文件流通常是缓冲的,所以在流结束之前到达文件的末尾。

我仍在努力理解你下面的答案,以及目的是什么表示_eof(),如果它总是返回1,即使您没有阅读任何东西(在第一个字符之后)。

为了回答这个问题,_eof的目的是确定当使用_open和_read直接处理文件描述符时,而不是当使用fopen和fread或getc处理文件流时,是否已到达文件末尾。

相关内容

  • 没有找到相关文章

最新更新