2013-04-09 91 views
2

下面是代码:eof()返回什么?

string fname = "/home/jack/example.csv"; 
ifstream csvin(fname.c_str()); 
if (csvin.eof()) { 
    do_something; 
} 

我的问题是:在什么情况下eof()返回true。我有以下选项:

  1. 文件不存在。
  2. 文件为空。
  3. 文件不存在或为空。

不幸的是documentation没有帮助,因为我不知道eofbit error state flag的意思。我也不明白End-of-File is reached in the sequence associated with the stream是什么意思。我假定c_str()返回一些迭代器,如果它已经被某些东西使用了,它可能已经达到了它的末尾。但是,我对c_str()的结果是新鲜的简单情况感兴趣,如果文件不存在,它将返回什么,如果文件为空,它将返回什么?

EDITED

我只是想知道什么是在两种情况下上面给出的代码返回:

  1. 文件不存在。
  2. 文件为空。
+0

通常,它是这样写的:while(!csvin.eof()){do_something();} – 2013-04-09 11:58:27

+3

@Gearoid No.除非“通常”,你的意思是“通常在破损的代码中” – 2013-04-09 11:59:51

+1

* *已领导导致你在一个循环,作为**,该网站很容易做**。将此网站视为您的第一个来源。 http://en.cppreference.com/w/cpp/io/basic_ios/eof – 2013-04-09 12:10:38

回答

4

EOF()返回true,当你在你从正在读取数据流中的位置已经到达了文件的末尾。它实际上返回eof标志的值,该值在读取文件结尾(尝试读取过去)时设置。查看C++: .eof on an empty file以了解关于eof和空文件的讨论!

+0

这将是很好的一些原因downvoting。 – 2013-04-09 12:08:32

+2

我没有downvote,但你的答案是不正确的。当您尝试读取*过去*文件的末尾时,eof位会被设置。如果你只读了最后一个字节,eof还没有设置**。这就是为什么如此多的'while(!eof())'构造失败如此悲惨的原因:他们认为,因为上一次操作成功,下一次操作也会成功...... – DevSolar 2013-04-09 12:13:01

+0

@DevSolar谢谢,我澄清了。 – 2013-04-09 12:16:47

2

eof返回true如果设置了eofbit标志(表示在ifstream的情况下达到文件的结尾)。

当输入操作尝试读取数据流的末尾(iow:到达流的末尾)时,可以通过流上的所有输入操作(例如,a read)设置eofbit标志。正如在评论中指出的那样,即使从概念上讲,只要最后一个字符被读取(或者没有读取任何空的流),流的末尾就会到达,但流直到它尝试读取另一个字符时才会知道。有关更多详细信息,请参阅每个输入操作的文档。

请注意,构建流不是输入操作,因此在您显示的代码示例中,eofbit在到达if语句时不会被设置。 如果构造流由于某种原因失败(例如,不存在的文件),则将设置失败位,可以使用fail进行检查。

编辑:看你的编辑,我会说出上述希望多一点明确:

在您发布的代码中,if条件永远不会计算为true,因为ifstream构造函数不设置eofbit。

在文件不存在的情况下,failbit将设置,您可以检查像这样:

if (csvin.fail()) { 
    // oops : failed to open the file for reading (file doesn't exist, or has the wrong permissions, or ...) 
} 

在文件是空的情况下,构造不会抱怨,但流中的第一个输入操作将设置eofbit。在完成第一次输入操作后,您可以使用eof检查是否已达到文件末尾。

+0

您的第二段含糊不清。 “到底流”的含义是什么?如果我打开一个空文件,我在尝试任何输入之前已“到达”流的末尾。我想你应该澄清一点。 (关键当然是,这个流试图看一个角色,而没有一个,尽管这也引发了一个问题:流何时试图看一个角色,有些输入需要预见性,其他没有。) – 2013-04-09 13:11:59

+0

@JamesKanze:公平点,并相应地添加了一些澄清。当谈到“到达流的末端”时,我正在从流代码的pov - 而不是概念上谈论。两者之间确实存在含糊之处。 – 2013-04-09 13:43:11

1

eof()回报true如果在流最后一次操作试图读到文件的最后一个字节。注意它告诉你一些关于上一次操作成功的事情,而不是关于下一次操作成功的事实。许多代码示例会做出错误的假设,告诉您有关下一个操作的内容,从而导致代码不会按预期运行。

+1

我不同意你的第二句话。但它取决于'eof()'返回的内容(以及操作是否成功)。如果'eof()'返回true,它会告诉你下一个操作将失败。如果它返回false,它会告诉你前面的操作没有因为文件结束而失败。 (可能因其他原因失败。) – 2013-04-09 13:15:04

1

eofbit被设置时,实际上有一小部分的实现依赖关系为 。它需要设置 如果在读什么课程(eof()返回,当且仅当eofbit设置。真 函数)(格式化或 格式化),以streambuf::sgetc()(或 其他的一个通话角色获得者)返回std::char_traits::eof()。 这并不总是清楚什么时候实现可能一个 字符前面—如果它得到文件的末尾这样做, 设置eofbit;如果它不做预测,它不会。

我也不能确定,以实现是否可以设置情况eofbit 它知道下一次读取必须返回eof, 而实际上不必进行读取;但是,我确信现有的实现不会。 (你真的想 eofbit设置当你寻求文件的结尾?)因此,在你的 的例子,你几乎肯定永远不会看到eof()返回 真实。

所有这一切都说明了为什么你几乎永远不会做input.eof()(或 input.good(),其中包括在其作为 值eofbit好)。尝试打开该文件后,通常的情况是 if (input.is_open()),虽然input.fail()可以很好地作为 。当读一个已打开的文件,我们测试 input.fail()所尝试的输入,通常通过使用布尔上下文的 流对象(即if (input),或if (!input))。 在已经检测到的故障,我们可能会使用 eof()来确定失败的原因是否是结束文件的 ,或一些其它错误(如试图输入一个 时int​​)。即使这样,它不是100%万无一失,即使有格式错误eof()可以 返回true。 (考虑:

std::istringstream s("1.3E+"); 
double d; 
s >> d; 

在这种情况下,s.eof()几乎肯定会返回true, dispite,输入失败,因为在 格式的错误,并因为文件末尾的不的事实。)