ifstream打开失败时如何获得错误信息

ifstream f; f.open(fileName); if ( f.fail() ) { // I need error message here, like "File not found" etc. - // the reason of the failure } 

如何获取错误信息为string?

每次失败的系统调用都会更新errno值。

因此,您可以通过使用类似于以下内容的更多信息了解ifstream打开失败时发生的情况:

 cerr << "Error: " << strerror(errno); 

但是,由于每个系统调用都会更新全局errno值,所以如果另一个系统调用在f.open的执行和errno使用之间触发错误,那么在multithreading应用程序中可能会遇到问题。

在具有POSIX标准的系统上:

errno是线程本地的; 在一个线程中设置它不会影响其在任何其他线程中的值。


编辑 (感谢Arne Mertz和其他人的评论):

e.what()似乎起初是一个更加C ++的 – 惯用的正确的方法来实现这个,但是这个函数返回的string是依赖于实现的(至less在G ++的libstdc ++中),这个string没有关于背后原因的有用信息错误…

您可以尝试让stream在失败时抛出exception:

 std::ifstream f; //prepare f to throw if failbit gets set std::ios_base::iostate exceptionMask = f.exceptions() | std::ios::failbit; f.exceptions(exceptionMask); try { f.open(fileName); } catch (std::ios_base::failure& e) { std::cerr << e.what() << '\n'; } 

然而, e.what()似乎并不是很有帮助:

  • 我试过它在Win7,Embarcadero RAD Studio 2010,它给“ios_base :: failbit设置”,而strerror(errno)给“没有这样的文件或目录”。
  • 在Ubuntu 13.04上,gcc 4.7.3例外说“basic_ios :: clear”(感谢arne )

如果e.what()对你不起作用(我不知道它会告诉你什么错误,因为这不是标准化的),请尝试使用std::make_error_condition (仅适用于C ++ 11):

 catch (std::ios_base::failure& e) { if ( e.code() == std::make_error_condition(std::io_errc::stream) ) std::cerr << "Stream error!\n"; else std::cerr << "Unknown failure opening file.\n"; } 

下面是@Arne Mertz的答案,从C ++ 11 std::ios_base::failureinheritance自system_error (请参阅http://www.cplusplus.com/reference/ios/ios_base/failure/ ),其中包含错误代码和消息strerror(errno)会返回。

 std::ifstream f; // Set exceptions to be thrown on failure f.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { f.open(fileName); } catch (std::system_error& e) { std::cerr << e.code().message() << std::endl; } 

这不打印No such file or directory. 如果fileName不存在。