ifstream f;
f.open(fileName);
if ( f.fail() )
{
// I need error message here, like "File not found" etc. -
// the reason of the failure
}
如何将错误消息作为字符串获取?
ifstream f;
f.open(fileName);
if ( f.fail() )
{
// I need error message here, like "File not found" etc. -
// the reason of the failure
}
如何将错误消息作为字符串获取?
每个失败的系统调用都会更新该errno
值。
因此,您可以通过以下方式获得更多关于ifstream
打开失败时会发生什么的信息:
cerr << "Error: " << strerror(errno);
但是,由于每个系统调用都会更新全局 errno
值,如果另一个系统调用在执行f.open
和使用errno
.
在具有 POSIX 标准的系统上:
errno 是线程本地的;在一个线程中设置它不会影响它在任何其他线程中的值。
编辑(感谢 Arne Mertz 和评论中的其他人):
e.what()
起初似乎是一种更 C++ 惯用正确的实现方式,但是这个函数返回的字符串是依赖于实现的,并且(至少在 G++ 的 libstdc++ 中)这个字符串没有关于错误背后原因的有用信息......
您可以尝试让流在失败时抛出异常:
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()
,但是,似乎不是很有帮助:
strerror(errno)
给出了“没有这样的文件或目录”。如果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++11std::ios_base::failure
继承自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
不存在,则打印。
您也可以抛出 a std::system_error
,如下面的测试代码所示。这种方法似乎产生比f.exception(...)
.
#include <exception> // <-- requires this
#include <fstream>
#include <iostream>
void process(const std::string& fileName) {
std::ifstream f;
f.open(fileName);
// after open, check f and throw std::system_error with the errno
if (!f)
throw std::system_error(errno, std::system_category(), "failed to open "+fileName);
std::clog << "opened " << fileName << std::endl;
}
int main(int argc, char* argv[]) {
try {
process(argv[1]);
} catch (const std::system_error& e) {
std::clog << e.what() << " (" << e.code() << ")" << std::endl;
}
return 0;
}
示例输出(Ubuntu w/clang):
$ ./test /root/.profile
failed to open /root/.profile: Permission denied (system:13)
$ ./test missing.txt
failed to open missing.txt: No such file or directory (system:2)
$ ./test ./test
opened ./test
$ ./test $(printf '%0999x')
failed to open 000...000: File name too long (system:36)
上面的std::system_error
例子有点不正确。std::system_category()
将从系统的本机错误代码工具映射错误代码。对于 *nix,这是errno
. 对于 Win32,它是GetLastError()
. 即,在 Windows 上,上面的示例将打印
failed to open C:\path\to\forbidden: The data is invalid
因为 EACCES 是 13,这是 Win32 错误代码 ERROR_INVALID_DATA
要修复它,要么使用系统的本机错误代码工具,例如在 Win32 上
throw new std::system_error(GetLastError(), std::system_category(), "failed to open"+ filename);
或者使用 errno and std::generic_category()
,例如
throw new std::system_error(errno, std::generic_category(), "failed to open"+ filename);