Урок №220. Базовий файловий ввід і вивід

  Юрій  | 

  Оновл. 13 Тра 2021  | 

 78

Робота файлового вводу/виводу в мові C++ майже аналогічна роботі звичайних потоків вводу/виводу (але зі своїми нюансами).

Класи файлового вводу/виводу

Є три основні класи файлового вводу/виводу в мові C++:

   ifstreamдочірнім класу istream);

   ofstream (є дочірнім класу ostream);

   fstream (є дочірнім класу iostream).

За допомогою цих класів можна виконувати однонаправлений файловий ввід, однонаправлений файловий вивід і двонаправлений файловий ввід/вивід. Для їх використання потрібно всього лише підключити заголовок fstream.

На відміну від потоків cout, cin, cerr і clog, які відразу ж можна використовувати, файлові потоки повинні бути явно встановлені програмістом. Тобто, щоб відкрити файл для читання і/або запису, потрібно створити об’єкт відповідного класу файлового вводу/виводу, вказавши ім’я файлу в якості параметра. Потім, за допомогою оператора вставки (<<) або оператора вилучення (>>), можна записувати дані в файл або зчитувати вміст файлу. Після виконання даних дій потрібно закрити файл — явно викликати метод close() або просто дозволити файловій змінній вводу/виводу вийти з області видимості (деструктор файлового класу вводу/виводу закриє цей файл автоматично замість нас).

Файловий вивід

Для запису в файл використовується клас ofstream. Наприклад:

Якщо ви заглянете в каталог вашого проекту (ПКМ по вкладці з назвою вашого файлу .cpp в Visual Studio > “Открыть содержащую папку”), то побачите файл з ім’ям SomeText.txt, в якому знаходяться наступні рядки:

See line #1!
See line #2!

Зверніть увагу, ми також можемо використати метод put() для запису одного символу в файл.

Файловий ввід

Тепер ми спробуємо прочитати вміст файлу, який створили в попередньому прикладі. Зверніть увагу, ifstream поверне 0, якщо ми досягли кінця файлу (це зручно для визначення «довжини» вмісту файлу). Наприклад:

Результат виконання програми:

See
line
#1!
See
line
#2!

Хм, це не зовсім те, що ми хотіли. Як ми вже дізналися на попередніх уроках, оператор вилучення працює з «відформатованими даними», тобто він ігнорує всі пробіли, символи табуляції і символ нового рядка. Щоб прочитати весь вміст як є, без його ділення на частини (як у вищенаведеному прикладі), нам потрібно використати метод getline():

Результат виконання програми:

See line #1!
See line #2!

Буферизований вивід

Вивід в мові C++ може бути буферизований. Це означає, що все, що виводиться в файловий потік, не може відразу ж бути записано на диск (в конкретний файл). Це зроблено, в першу чергу, з міркувань продуктивності. Коли дані буфера записуються на диск, то це називається очищенням буфера. Одним із способів очищення буфера є закриття файлу. У такому випадку весь вміст буфера буде переміщено на диск, а потім файл буде закрито.

Буферизація виводу зазвичай не є проблемою, але при певних обставинах вона може викликати проблеми у необережних новачків. Наприклад, коли в буфері зберігаються дані, а програма передчасно завершує своє виконання (або в результаті збою, або шляхом виклику функції exit()). У таких випадках деструктори класів файлового вводу/виводу не виконуються, файли ніколи не закриваються, буфери не очищаються і наші дані губляться назавжди. Ось чому гарною ідеєю є явне закриття всіх відкритих файлів перед викликом функції exit().

Також буфер можна очистити вручну, використовуючи метод ostream::flush() або відправивши std::flush в вихідний потік. Будь-який з цих способів може бути корисний для забезпечення негайного запису вмісту буфера на диск в разі збою програми.

Цікавий нюанс: Оскільки std::endl; також очищає вихідний потік, то його надмірне використання (яке призводить до непотрібних очищень буфера) може вплинути на продуктивність програми (тому що очищення буфера в деяких випадках може бути витратною операцією). З цієї причини програмісти, які турбуються про продуктивність свого коду, часто використовують \n замість std::endl для вставки символу нового рядка у вихідний потік, щоб уникнути непотрібного очищення буфера.

Режими відкриття файлів

Що відбудеться, якщо ми спробуємо записати дані в уже існуючий файл? Повторний запуск вищенаведеної програми (найперша) показує, що вихідний файл повністю перезаписується при повторному запуску програми. А що, якщо нам потрібно додати дані в кінець файлу? Виявляється, конструктори файлового потоку приймають необов’язковий другий параметр, який дозволяє вказати програмісту спосіб відкриття файлу. В якості цього параметра можна передавати наступні флаги (які знаходяться в класі ios):

   app — відкриває файл в режимі додавання;

   ate — переходить в кінець файлу перед читанням/записом;

   binary — відкриває файл в бінарному режимі (замість текстового режиму);

   in — відкриває файл в режимі читання (за замовчуванням для ifstream);

   out — відкриває файл в режимі запису (за замовчуванням для ofstream);

   trunc — видаляє файл, якщо він вже існує.

Можна вказати відразу кілька флагів шляхом використання побітового АБО (|).

   ifstream за замовчуванням працює в режимі ios::in;

   ofstream за замовчуванням працює в режимі ios::out;

   fstream за замовчуванням працює в режимі ios::in АБО ios::out, що означає, що ви можете виконувати як читання вмісту файлу, так і запис даних в файл.

Тепер давайте напишемо програму, яка додасть два рядки в раніше створений нами файл SomeText.txt:

Тепер, якщо ми подивимося вміст файлу SomeText.txt (запустимо одну з вищенаведених програм для читання файлу або відкриємо цей файл в каталозі проекту), то побачимо наступне:

See line #1!
See line #2!
See line #3!
See line #4!

Явне відкриття файлів за допомогою функції open()

Точно так же, як ми явно закриваємо файл за допомогою методу close(), ми можемо явно відкривати файл за допомогою функції open(). Функція open() працює аналогічно конструкторам класу файлового вводу/виводу: приймає ім’я файлу і режим (необов’язково), в якому потрібно відкрити файл, в якості параметрів. Наприклад:

Результат:

See line #1!
See line #2!
See line #3!

На цьому все! На наступному уроці ми розглянемо рандомний файловий ввід/вивід.

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (Немає Оцінок)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *