ifstream:检查是否成功打开文件

63

一位同事告诉我,这段代码:

std::ifstream stream(filename.c_str());
if (!stream)
{
    throw std::runtime_error("..");
}

如果打开文件成功,ifstream 将返回0。他说这是错误的。我的代码可以工作,但我想找到文档看一下如何检查打开是否成功。你能指点我吗?

4个回答

67

operator! 被重载 用于 std::ifstream,所以你可以这样做。

但在我看来,这是一种非常糟糕的操作符重载滥用(由标准委员会决定)。如果你只是使用 if (stream.fail()),你要检查的更加显式明确。


18
别忘了检查 stream.bad()stream.good()stream.fail()stream.is_open()。唉... - Inverse
17
叹号符号“!”被重载用于检查输入流状态是否为“fail”或“bad”。 - Martin Beckett
10
这里没有“滥用”的行为。 - Lightness Races in Orbit
5
我认为“fail”比运算符更加含糊或容易造成混淆,因为尽管其名称为“fail”,但它会检查failbit和badbit两个标志位。 - Useless
4
因为它(在很大程度上)是一种特殊的情况 - 这种使用感叹号来表示“失败”的方式并不普遍,因此在我看来,它会降低可读性。 - Oliver Charlesworth
显示剩余4条评论

14
你可以通过调用流的ios::exceptions()函数并使用正确的掩码使特定的流在eof/fail/bad中的任何一种情况下抛出异常。因此,你可以将上面初始问题中的示例重写为:
std::ifstream stream;
stream.exceptions(std::ios::failbit | std::ios::badbit);
stream.open(filename.c_str());

在这里,当failbit或badbit被设置时,流将抛出异常。例如,如果ifstream::open()失败,它会设置failbit并抛出异常。当然,如果流上设置了这些位中的任何一个,稍后也会抛出异常,因此此重写与初始示例不完全相同。您可以调用

stream.exceptions(std::ios::goodbit);

取消流上的所有异常并返回检查错误。

很不幸,在迭代文件结束时会出现异常... libc++abi: terminating with uncaught exception of type std::__1::ios_base::failure: ios_base::clear: unspecified iostream_category error - Hugh Perkins

11

您也可以使用is_open()来检查它是否起作用,但是!被允许的(它不是检查零,而是一个特殊的! 的重载

编辑:
只是出于兴趣-为什么不会引发异常?
是因为在异常之前引入了流
还是我们进入了旧的C ++事物-只是错误,不够异常。


1
我想了20年,为什么需要存在一个不成功的ifstream对象...也许在另外20年内,这个问题可能会得到解决(通过引入另一个构造函数,带有额外的please_throw()参数?)。希望到那时,错误的原因将包含在异常对象中。 - user8434768

5
你的同事是错误的。也许他忘了你不是在写C语言。
代码是无可挑剔的。这正是你应该检查流状态的正确方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接