Когда будет поток: open fail?
Я пытаюсь попробовать, ловить, вызывать утверждения в С++ для обработки файлов, и я написал фиктивный код, чтобы поймать все ошибки. Мой вопрос заключается в том, чтобы проверить, правильно ли я прав, мне нужна ошибка. Теперь я легко могу проверить infile.fail()
, просто не создавая файл требуемого имени в каталоге. Но как я могу проверить то же самое для outfile.fail()
(outfile
is ofstream
, где as infile
- ifstream
). В этом случае будет ли значение для outfile.fail()
истинным?
пример кода [по комментариям к ответу ундерссона, упрощенному, чтобы сделать проблему более ясной -zack]:
#include <fstream>
using std::ofstream;
int main()
{
ofstream outfile;
outfile.open("test.txt");
if (outfile.fail())
// do something......
else
// do something else.....
return 0;
}
Ответы
Ответ 1
open(2)
man-страница в Linux имеет около 30 условий. Некоторые интересные:
- Если файл существует, и у вас нет разрешения на его запись.
- Если файл не существует, и у вас нет разрешения (в директории) для его создания.
- Если у вас нет разрешения на поиск в каком-либо родительском каталоге.
- Если вы передадите фиктивный
char*
для имени файла.
- Если при открытии файла устройства нажмите CTRL-C.
- Если ядро обнаружило слишком много символических ссылок при разрешении имени.
- Если вы попытаетесь открыть каталог для записи.
- Если длина пути слишком длинная.
- Если ваш процесс имеет слишком много файлов, открывайте их уже.
- Если в системе слишком много файлов, открываемых уже.
- Если имя пути относится к файлу устройства, и в системе нет такого устройства.
- Если в ядре закончилась память.
- Если файловая система заполнена.
- Если компонент пути не является каталогом.
- Если файл находится в файловой системе только для чтения.
- Если файл является исполняемым файлом, который в настоящее время выполняется.
Ответ 2
По умолчанию и по дизайну потоки С++ никогда не вызывают исключения при ошибке. Вы не должны пытаться писать код, который предполагает, что они делают, даже если их можно получить. Вместо этого в вашей логике приложения проверяйте каждую операцию ввода-вывода на ошибку и обрабатывайте ее, возможно, выбирая собственное исключение, если эта ошибка не может быть решена в конкретном месте, которое оно встречается в вашем коде.
Канонический способ тестирования потоков и потоков - это не проверка определенных флагов потока, если только не нужно. Вместо этого:
ifstream ifs( "foo.txt" );
if ( ifs ) {
// ifs is good
}
else {
// ifs is bad - deal with it
}
аналогично для операций чтения:
int x;
while( cin >> x ) {
// do something with x
}
// at this point test the stream (if you must)
if ( cin.eof() ) {
// cool - what we expected
}
else {
// bad
}
Ответ 3
Чтобы сбой ofstream::open
завершился неудачей, вам необходимо организовать невозможность создания именованного файла. Самый простой способ сделать это - создать каталог с таким же именем перед запуском программы. Вот почти полная демо-программа; чтобы надежно удалить тестовый каталог тогда и только тогда, когда вы его создали, я оставляю как упражнение.
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <cstring>
#include <cerrno>
using std::ofstream;
using std::strerror;
using std::cerr;
int main()
{
ofstream outfile;
// set up conditions so outfile.open will fail:
if (mkdir("test.txt", 0700)) {
cerr << "mkdir failed: " << strerror(errno) << '\n';
return 2;
}
outfile.open("test.txt");
if (outfile.fail()) {
cerr << "open failure as expected: " << strerror(errno) << '\n';
return 0;
} else {
cerr << "open success, not as expected\n";
return 1;
}
}
Нет никакого хорошего способа гарантировать, что запись в файл fstream завершится неудачно. Я, вероятно, создаю mock ostream, который не смог выполнить запись, если мне нужно было проверить это.