Подтвердить что ты не робот

Как получить сообщение об ошибке при сбое openstream

ifstream f;
f.open(fileName);

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

Как получить сообщение об ошибке как строку?

4b9b3361

Ответ 1

Каждый системный вызов, который не обновляет значение errno.

Таким образом, вы можете получить дополнительную информацию о том, что происходит, когда сбой ifstream открывается с помощью следующего:

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

Однако, поскольку каждый системный вызов обновляет глобальное значение errno, у вас могут быть проблемы в многопоточном приложении, если другой системный вызов вызывает ошибку между выполнением f.open и использованием errno.

В системе с стандартом POSIX:

errno является поточно-локальным; установка его в один поток не влияет на его значение в любом другом потоке.


Изменить (спасибо Арне Мерцу и другим людям в комментариях):

e.what() казался сначала более понятным для С++ - идиоматически правильным способом его реализации, однако строка, возвращаемая этой функцией, зависит от реализации и (по крайней мере, в g++ libstdС++), эта строка не содержит никакой полезной информации о причине за ошибкой...

Ответ 2

Вы можете попытаться позволить потоку исключить исключение при ошибке:

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:: набор сбоев", тогда как strerror(errno) дает "Нет такого файла или каталога".
  • В Ubuntu 13.04, gcc 4.7.3 исключение говорит "basic_ios:: clear" (благодаря arne)

Если e.what() не работает для вас (я не знаю, что он скажет вам об ошибке, так как это не стандартизировано), попробуйте использовать std::make_error_condition (только для С++ 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";
}

Ответ 3

Следуя за ответом @Arne Mertz, с С++ 11 std::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 не существует.