Файловые потоки. Открытие и закрытие файлов. Режимы доступа

Практический курс по C/C++: https://stepik.org/course/193691

В языке С++ существует набор классов, упрощающих работу с файловыми потоками (или, попросту, с файлами). Они следующие:

  • ifstream – для чтения данных из файла;
  • ofstream – для записи данных в файл;
  • fstream – для записи и чтения данных из файла.

И аналогичные им классы с дополнительной буквой w, означающей работу с данными типа wchar_t:

  • wifstream – для чтения данных из файла;
  • wofstream – для записи данных в файл;
  • wfstream – для записи и чтения данных из файла.

В рамках этого курса мы ограничимся первыми тремя классами. Три других используются аналогичным образом.

Для их использования в программе вначале необходимо подключить заголовочный файл с именем fstream:

#include <fstream>

После этого можно создавать объекты этих классов. Например:

#include <iostream>
#include <fstream>
 
using std::cout;
using std::cin;
using std::endl;
 
int main()
{
    std::ofstream ofs;
    std::ifstream ifs;
    return 0;
}

Чтобы связать выходной и входной потоки с определенными файлами, используется метод open следующим образом:

    ofs.open("ofs.dat");
    ifs.open("ifs.dat");

Здесь файл ofs.dat открывается на запись в текстовом режиме доступа; файл ifs.dat – открывается на чтение также в текстовом режиме доступа. Что это за режим, я думаю, вы хорошо помните из курса по языку Си?

После запуска программы в текущем (рабочем) каталоге появится пустой файл с именем ofs.dat.

Также открытие файла можно делать сразу в момент создания объектов классов потоков следующим образом:

    std::ofstream ofs("ofs.dat");
    std::ifstream ifs("ifs.dat");

Результат будет аналогичным.

Далее, мы знаем, что после завершения работы с файлами их обязательно нужно закрывать. Для этого используется метод close() объектов ofs и ifs:

    ofs.close();
    ifs.close();

И последний важный штрих в этой схеме открытия и закрытия файлов. Нам нужно проверить, что файл был открыт успешно, прежде чем начинать что-либо в него записывать или считывать. Для этого предусмотрен метод is_open(). Я для его демонстрации запишу следующие строчки:

    cout << (ofs.is_open() ? "Файл ofs.dat открыт" : "Ошибка открытия файла ofs.dat") << endl;
    cout << (ifs.is_open() ? "Файл ifs.dat открыт" : "Ошибка открытия файла ifs.dat") << endl;

После запуска программы увидим в консоли сообщения:

Файл ofs.dat открыт
Ошибка открытия файла ifs.dat

То есть, на запись файл был открыт успешно, а на чтение – с ошибкой. И это логично, так как файла ifs.dat в рабочем каталоге не существует.

Режимы доступа к файлам

Давайте теперь посмотрим, какие режимы доступа к файлам мы можем прописывать при их открытии. Основные, следующие:

  • ios::in – для чтения (только для объектов классов ifstream или fstream);
  • ios::out – для записи; прежние данные удаляются (только для объектов классов ofstream или fstream);
  • ios::app – для дозаписи; прежние данные не удаляются;
  • ios::ate – при открытии указатель файла смещается в конец;
  • ios::binary – открытие файла в бинарном режиме доступа.

Указанные флаги используются, как самостоятельно, так и в допустимых комбинациях с другими флагами. Например, мы можем указать открыть файл на дозапись:

int main()
{
    using std::ios;
    std::ofstream ofs("ofs.dat");
    std::ifstream ifs("ifs.dat", ios::app);
    ...
    return 0;
}

Обратите внимание, что после выполнения программы файл ifs.dat создается и успешно открывается благодаря изменению режима открытия. Сам файл, конечно же, будет пустым.

Или можно записать следующую комбинацию флагов для открытия файлов в бинарном режиме доступа:

    std::ofstream ofs("ofs.dat", ios::out | ios::binary);
    std::ifstream ifs("ifs.dat", ios::app | ios::binary);

И так далее. Мы можем прописывать, как самостоятельные флаги, так и их допустимые комбинации. Допустимость можно определить с позиции здравого смысла. Либо, почитать в документации.

Итак, мы с вами разобрали, как открывать файлы в разных режимах, проверять корректность открытия файлового потока и закрывать его. На следующем занятии посмотрим, как непосредственно выполняются файловые операции чтения/записи через объекты классов ifstream, ofstream  и fstream.

Практический курс по C/C++: https://stepik.org/course/193691

Видео по теме