c++ - 为什么::feof() 不同于::_eof(::fileno())?

标签 c++ file-io stream filestream

免责声明:不要使用 ::feof() 作为循环条件。 例如,请参阅以下问题的答案:file reading: feof() for binary files

但是,我有“真实的”代码演示了一个问题,它没有使用 ::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() 是“非缓冲的”并认为整个文件已经“读入”(因为整个文件将适合从磁盘读入的第一个 block )。但是,鉴于这些功能的目的,这不可能是真的。所以,我真的很茫然。

这是怎么回事?

(文件以“文本”方式打开,是十几行左右的ASCII文本文件,MSVS2008,Win7/64。)

最佳答案

I suppose it is conceivable that ::feof() is "buffered" (so it works correctly) while ::_eof() is "un-buffered" and thinks the whole file is "read-in" already (because the whole file would have fit into the first block read in from disk). However, that can't possibly be true given the purpose of those functions. So, I'm really at a loss.

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

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

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 时,您是在询问是否已到达文件 stream 的末尾。由于文件流通常被缓冲,因此在流结束之前到达文件末尾。

I'm still trying to understand your answer below, and what the purpose is for _eof() if it always returns 1 even when you didn't read anything (after the first char).

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

关于c++ - 为什么::feof() 不同于::_eof(::fileno())?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8783499/

相关文章:

c++ - 使用单独编译时返回 typedef 类型

c++ - Win32API - 如何从进程句柄中获取进程的文件名?

C++ 指针数组参数

python - 如何取消读取python中的一行

c++ - boost::asio::write UNICODE

C++ 食物菜单(使用 do while 循环)

java - 如何使用 Files.walk 一次读取子目录中的所有文件?

ruby - 获取S3对象的下载流并将其传递给ruby中的另一个方法

java - 如何将 iText 文档转换为 javax.activation.DataSource?

python - 为什么在 python 中调用 file.read 会使我的文件充满垃圾?