Состояние потока
Каждый поток имеет связанное с ним состояние. Состояния потока описываются в классе ios в виде перечисления enum.
public:
enum io_state {
goodbit, // нет ошибки 0Х00
eofbit, // конец файла 0Х01
failbit, // последняя операция не выполнилась 0Х02
badbit, // попытка использования недопустимой операции 0Х04
hardfail // фатальная ошибка 0Х08 };
Флаги, определяющие результат последней операции объектом ios, содержатся в переменной state. Получить значение этой переменной можно с помощью функции int rdstate().
Кроме того, проверить состояние потока можно следующими функциями:
int bad(void); // 1, badbit или hardfail
int eof(void); // 1, если eofbit
int fail(void); // 1, если failbit, badbit или hardfail
int good(void); // 1, если goodbit
Если операция >> используется для новых типов данных, то при её перегрузке необходимо предусмотреть соответствующие проверки.
Файловый ввод-вывод
Потоки для работы с файлами создаются как объекты следующих классов:
ofstream - запись в файл;
ifstream - чтение из файла;
fstream - чтение/запись.
Для создания потоков имеются следующие конструкторы:
fstream(); создает поток, не присоединяя его ни к какому файлу.
fstream(constchar *name, int mode, int p = filebuf::openprot); создает поток, присоединяет его к файлу с именем name, предварительно открыв файл, устанавливает для него режим mode и уровень защиты p. Если файл не существует, то он создается. Для mode = ios::out, если файл существует, то его размер будет усечен до нуля.
Флаги режима определены в классе ios и имеют следующие значения:
in - для чтения
out - для записи
ate - индекс потока помещен в конец файла. Чтение больше не допустимо, выводные данные записываются в конец файла;
app - поток открыт для добавления данных в конец. Независимо от seekp() данные будут записываться в конец;
trunc - усечение существующего потока до нуля;
nocreate - команда открытия потока будет завершена неудачно, если файл не существует;
noreplace - команда открытия потока будет завершена неудачно, если файл существует;
binary - поток открывается для двоичного обмена.
Следующая операция открытия файла открывает файл для вывода, используя режим ios::noreplace, чтобы предотвратить перезапись существующего файла:
ifstream output_file("FIlename.EXT", ios::out | ios::noreplace).
Если при создании потока он не присоединен к файлу, то присоединить существующий поток к файлу можно функцией
void open(const char *name, int mode, int p = filebuf::openprot);
Функция
void fstream base::close();
сбрасывает буфер потока, отсоединяет поток от файла и закрывает файл. Эту функцию необходимо явно вызвать при изменении режима работы с потоком. Автоматически она вызывается только при завершении программы.
Таким образом, создать поток и связать его с файлом можно тремя способами:
Создается объект filebuf
filebuf fbuf;
Объект filebuf связывается с устройством (файлом)
fbuf.open("имя", ios::in);
Создается поток и связывается с filebuf
istream stream(&fbuf);
Создается объект fstream (ifstream, ofstream)
fstream stream;
Открывается файл, который связывается через filebuf с потоком
stream.open("имя", ios::in);
Создается объект fstream, одновременно открывается файл, который связывается с потоком
fstream stream("имя", ios::in).
ОПРЕДЕЛЕНИЕ КОНЦА ФАЙЛА
Обычной файловой операцией в программах является чтение содержимого файла, пока не встретится конец файла. Чтобы определить конец файла, ваши программы могут использовать функцию еоf потокового объекта. Эта функция возвращает значение 0, если конец файла еще не встретился, и 1, если встретился конец файла. Используя цикл while, программы могут непрерывно читать содержимое файла, пока не найдут конец файла, как показано ниже:
while (! input_file.eof())
{// Операторы}
В данном случае программа будет продолжать выполнять цикл, пока функция eof возвращает ложь (0). Следующая программа использует функцию eof для чтения содержимого файла INFO.DAT, пока не достигнет конца файла:
void main (void)
{ifstream input_file("INFO.DAT");
char line[64];
while (! input_file.eof())
{input_file.getline(line, sizeof(line));
cout<<line<<endl;}}
Аналогично, следующая программа читает содержимое файла по одному слову за один раз, пока не встретится конец файла:
void main(void)
{ifstream input_file("INFO.DAT");
char word[64] ;
while (! input_file.eof())
{input_file>> word;
cout<< word <<endl;}}
И наконец, следующая программа читает содержимое файла по одному символу за один раз, используя функцию get, пока не встретит конец файла:
void main(void)
{ifstream input_file("BOOKINFO.DAT");
char letter;
while (! input_file.eof())
{letter = input_file.get();
cout<< letter;}}
ПРОВЕРКА ОШИБОК ПРИ ВЫПОЛНЕНИИ ФАЙЛОВЫХ ОПЕРАЦИЙ
Если ваша программа пишет данные в файл, вам необходимо убедиться, что операция прошла успешно (к примеру, отсутствие места на диске, скорее всего, помешает записи данных). Чтобы помочь программам следить за ошибками, вы можете использовать функцию fail файлового объекта. Если в процессе файловой операции ошибок не было, функция возвратит ложь (0). Однако, если встретилась ошибка, функция fail возвратит истину. Например, если программа открывает файл, ей следует использовать функцию fail, чтобы определить, произошла ли ошибка, как это показано ниже:
ifstream input_file("FILENAME.DAT");
if (input_file.fail())
{cerr<< "Ошибка открытия FILENAME.EXT" <<endl;
exit(1);}
ЗАКРЫТИЕ ФАЙЛА, ЕСЛИ ОН БОЛЬШЕ НЕ НУЖЕН
При завершении программы операционная система закроет открытые ею файлы. Однако, как правило, если программе файл больше не нужен, она должна его закрыть. Для закрытия файла программа должна использовать функцию close:
input_file.close ().