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
}
Как получить сообщение об ошибке в виде строки?
cerr << "Error code: " << strerror(errno); // Get some info as to why
кажется относящимся к вопросу.
strerror(errno)
работает. Отправьте это как ответ, я приму это.
Ответы:
Каждый неудачный системный вызов обновляет errno
значение.
Таким образом, вы можете получить больше информации о том, что происходит при ifstream
сбое открытия, используя что-то вроде:
cerr << "Error: " << strerror(errno);
Однако, поскольку каждый системный вызов обновляет глобальное errno
значение, у вас могут возникнуть проблемы в многопоточном приложении, если другой системный вызов вызывает ошибку между выполнением f.open
и использованием errno
.
В системе со стандартом POSIX:
errno является локальной для потока; установка его в одном потоке не влияет на его значение в любом другом потоке.
Изменить (спасибо Арне Мерцу и другим людям в комментариях):
e.what()
Сначала казалось, что это более правильный с ++ - идиоматически правильный способ реализации этого, однако строка, возвращаемая этой функцией, зависит от реализации и (по крайней мере, в libstdc ++ G ++) эта строка не содержит полезной информации о причине ошибки ...
e.what()
похоже, не дает много информации, см. обновления моего ответа.
errno
использует локальное хранилище потоков в современных операционных системах. Однако нет никакой гарантии, что fstream
функции не будут работать errno
после ошибки errno. Базовые функции могут вообще не устанавливаться errno
(прямые системные вызовы в Linux или Win32). Это не работает во многих реализациях в реальном мире.
e.what()
всегда выводит одно и то же сообщение " iostream stream error
"
warning C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1> C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\string.h(168) : see declaration of 'strerror'
Вы можете попробовать разрешить потоку генерировать исключение в случае сбоя:
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";
}
strerror(errno)
опубликованный в комментариях работает и очень прост в использовании. Я думаю, что e.what
сработает, т.к. errno
работает.
e.what()
это будет то strerror
, что вернется в потокобезопасном режиме. Оба, вероятно, будут зависеть от платформы.
exception.what()
. Может быть, это хорошая возможность погрузиться в исходный код libstdc ++ :-)
basic_ios::clear
, больше ничего. Это не очень полезно. Вот почему я не публиковал;)
Следуя ответу @Arne Mertz, начиная с C ++ 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
не существует.
iostream stream error
.
iostream error
. На каком компиляторе вы это тестировали? Действительно ли какой-либо компилятор предоставляет читаемую пользователем причину сбоя?
unspecified iostream_category error
.
Вы также можете бросить, 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)