Получение значимых сообщений об ошибках от fstream в C++
Каков наилучший способ получить осмысленные сообщения об ошибках доступа к файлам переносимым способом из std::fstreams? Примитивность badbits
а также failbits
становится немного раздражающим. Я уже писал свои собственные иерархии исключений для win32 и POSIX, и это было гораздо более гибким, чем то, как это делает STL.
Я получаю "basic::ios_clear" как сообщение об ошибке от what
метод пониженного улова (std::exception
) из fstream
который имеет исключения включены. Для меня это не имеет большого значения, хотя я знаю, в чем проблема, и я хотел бы, чтобы моя программа была более информативной, чтобы через несколько месяцев после начала развертывания моя жизнь стала проще.
Есть ли что-то в Boost, чтобы извлечь значимые сообщения из fstream
реализация кроссплатформенной и кросс-STL-реализации?
3 ответа
Никто не мешает вам также проверить errno
/ strerror
(например, в вашем обработчике исключений) для более конкретной причины сбоя.
ОБНОВЛЕНИЕ - относительно переносимости
Кстати, IIRC Visual Studio fstream
реализация вызывает _open
/ _read
/ _write
/так далее. Методы CRT, которые устанавливают errno
, Microsoft не дает никаких гарантий относительно GetLastError
по-прежнему содержит правильное значение после возврата методов CRT. Idem для реализаций cygwin, mingw и т. Д., Которые устанавливают errno
без претензий или гарантий о GetLastError
,
Поэтому я подтверждаю свое требование, что все, что вам нужно, может и, следовательно, хотите сделать, это проверить errno
,
Теперь, учитывая все вышесказанное, если вы все еще хотите усложнить свою жизнь и переобучиться, используя Boost::System
вместо того, чтобы просто звонить strerror
тогда я думаю, мое определение и ваше определение элегантности и простоты не совпадают.:)
Какую информацию вы хотите? badbit
указывает на ошибку ввода / вывода. eofbit
указывает на eof. failbit
указывает на ошибку разбора.
В любом случае, чтобы исключить одно решение, я не думаю, что вы можете переопределить функции ввода нативного типа из-за ADL. Вы могли бы реализовать operator>>(istream, input_safe_int)
где input_safe_int
построен из int&
, Положить try
блок внутри и т. д.
Мне повезло поймать std::ios_base::failure
а затем вновь поднимая а ,std::system_error
с использованием :
terminate called after throwing an instance of 'std::system_error'
what(): broken/path: No such file or directory
#include <fstream>
int main() {
const std::string filename{ "broken/path" };
try {
std::ifstream file{ filename };
file.exceptions(std::ios::failbit); // std::ios_base_failure is thrown here
} catch (std::ios_base::failure&) {
throw std::system_error{ errno, std::generic_category(), filename };
}
}
Это работает в UNIX и Windows, потому что "Все
errno
значения являются… UNIX-совместимыми »(исходный код ).