Файловые потоки ввода/вывода.
Для осуществления операций с файлами предусмотрено три класса: ifstream, ofstream и fstream. Эти классы являются производными, соответственно, от классов istream, ostream и iostream. Поскольку эти последние классы, в свою очередь, являются производными от класса ios, классы файловых потоков наследуют все функциональные возможности своих родителей (перегруженные операции << и >> для встроенных типов, функции и флаги форматирования, манипуляторы и пр.). Для реализации файлового ввода-вывода нужно включить в программу заголовочный файл fstream.h.
Существует небольшое отличие между использованием предопределенных и файловых потоков. Файловый поток должен быть связан с файлом прежде, чем его можно будет использовать. С другой стороны, предопределенные потоки могут использоваться сразу после запуска программы, даже в конструкторах статических классов, которые выполняются даже раньше вызова функции main(). Можно позиционировать файловый поток в произвольную позицию в файле, в то время как для предопределенных потоков это обычно не имеет смысла.
Для создания файлового потока эти классы предусматривают следующие формы конструктора:
создать поток, не связывая его с файлом:
ifstream();
ofstream();
fstream();
создать поток, открыть файл и связать поток с файлом:
ifstream(const char *name, ios::openmode mode = ios::in) ;
ofstream(const char* name, ios::openmode mode=ios::out | ios::trunc);
fstream(const char * name, ios::openmode mode = ios::in | ios::out);
Чтобы открыть файл для ввода или вывода, можно использовать вторую форму нужного конструктора
fstream fs("FileName.dat");
или вначале создать поток с помощью первой формы конструктора, а затем открыть файл и связать поток с открытым файлом, вызвав функцию-член open(). Эта функция определена в каждом из классов потокового ввода-вывода и имеет следующие прототипы:
void ifstream::open(const char *name, ios::openmode mode = ios::in);
void ofstream::open
(const char * name, ios::openmode mode = ios::out | ios::trunc);
void fstream::open
(const char * name, ios::openmode mode = ios::in | ios::out);
Здесь name - имя файла, mode - режим открытия файла. Параметр mode является перечислением и может принимать значения, указанные в табл. 8.
Таблица 8
Режимы открытия и их назначение
Режим открытия | Назначение |
ios::in | Открыть файл для чтения |
ios::out | Открыть файл для записи |
ios::ate | Начало вывода устанавливается в конец файла |
ios::app | Открыть файл для добавления в конец |
ios::trunc | Усечь файл, то есть удалить его содержимое |
ios::binary | Двоичный режим операций |
Режимы открытия файла представляют собой битовые маски, поэтому можно задавать два или более режима, объединяя их побитовой операцией ИЛИ. В следующем фрагменте кода файл открывается для вывода с помощью функции open():
ofstream ofs;
ofs.open("FileName.dat");
Обратим внимание, что по умолчанию режим открытия файла соответствует типу файлового потока. У потока ввода или вывода флаг режима всегда установлен неявно. Например, для потока вывода в режиме добавления файла можно вместо оператора
ofstream ofs("FName.txt", ios::out | ios::app);
написать
ofstream ofs("FName.txt", ios::app);
Между режимами открытия файла ios::ate и ios::app имеется небольшая разница.
Если файл открывается в режиме добавления, весь вывод в файл будет осуществляться в позицию, начинающуюся с текущего конца файла, безотносительно к операциям позиционирования в файле. В режиме открытия ios::ate (от английского "at end") можно изменить позицию вывода в файл и осуществлять запись, начиная с нее. Для потоков вывода режим открытия эквивалентен ios::out | ios::trunc, то есть можно опустить режим усечения файла. Однако для потоков ввода-вывода его нужно указывать явно. Файлы, которые открываются для вывода, создаются, если они еще не существуют.
Если открытие файла завершилось неудачей, объект, соответствующий потоку, будет возвращать 0:
if (!ofs){ cout << "Файл не открыт\n";}
Проверить успешность открытия файла можно также с помощью функции-члена is_open(), имеющей следующий прототип:
int is_open() const;
Функция возвращает 1, если поток удалось связать с открытым файлом. Например,
if (!ofs.is_open()){ cout << "Файл не открыт\n"; return; }
Если при открытии файла не указан режим ios::binary, файл открывается в текстовом режиме и после того, как файл успешно открыт, для выполнения операций ввода-вывода можно использовать операторы извлечения и вставки в поток. Для проверки, достигнут ли конец файла, можно использовать функцию ios::eof(), имеющую прототип int eof();
Завершив операции ввода-вывода, необходимо закрыть файл, вызвав функцию-член close() с прототипом void close():
ofs.close();
Закрытие файла происходит автоматически при выходе потокового объекта из области существования, когда вызывается деструктор потока.