cha*_*ley 0 c++ file-io stream filestream
免责声明:不要::feof()用作你的循环条件. 例如,请参阅以下答案: 文件读取:二进制文件的feof()
但是,我有"真正的"代码,它演示了一个不能::feof()用作我的循环条件的问题,但是LOGICALLY,这是演示问题的最简单方法.
请考虑以下事项:我们一次迭代一个字符流:
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"
}
Run Code Online (Sandbox Code Playgroud)
上面的代码按预期工作: 文件一次处理一个char,然后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"
}
Run Code Online (Sandbox Code Playgroud)
我原以为他们会这样做. ::fileno()每次都正确返回(整数)文件描述符.但是,测试只::_eof(::fileno(my_file))运行一次,然后在第二次尝试时返回1(指示a EOF).
我不明白.
我认为可以想象::feof()是"缓冲"(因此它正常工作)而::_eof()"未缓冲"并且认为整个文件已经"读入"(因为整个文件将适合从第一个块读入)磁盘).但是,考虑到这些功能的目的,这可能不是真的.所以,我真的很茫然.
这是怎么回事?
(文件以"文本"形式打开,是带有大约十几行的ASCII文本文件,MSVS2008,Win7/64.)
我想可以想象:: feof()是"缓冲的"(因此它可以正常工作)而:: _ eof()是"未缓冲的"并认为整个文件已经"读入"(因为整个文件)将适合从磁盘读入的第一个块).但是,考虑到这些功能的目的,这可能不是真的.所以,我真的很茫然.
我不知道为什么你会认为"鉴于这些功能的目的,它不可能是真的." 这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"
}
Run Code Online (Sandbox Code Playgroud)
我会根据你的评论尝试详细说明一下.
当您调用fopen时,您将返回指向文件流的指针.底层流对象保留它自己的文件指针,该指针与与底层文件描述符关联的实际文件指针分开.
当您调用_eof时,您会询问是否已到达实际文件的末尾.当您调用feof时,您会询问是否已到达文件流的末尾.由于文件流通常是缓冲的,因此在流结束之前到达文件的末尾.
我仍然试图理解你的答案,以及_eof()的目的是什么,如果它总是返回1,即使你没有读过任何东西(在第一个字符之后).
要回答这个问题,_eof的目的是确定在使用_open和_read直接使用文件描述符时是否已到达文件末尾,而不是在使用fopen和fread或getc处理文件流时.