12. Файлы и потоки

Что такое потоки

Поток (stream) — это абстракция, с помощью которой программа обменивается данными с внешним миром. Потоки бывают:
  • входные (input) — для чтения данных (например, с клавиатуры или из файла);
  • выходные (output) — для записи данных (в консоль или в файл).

В C++ всё работает через потоки: `cin`, `cout`, `ifstream`, `ofstream`, `fstream` — всё это разные типы потоков.

Пример с консолью


#include <iostream>
using namespace std;

int main() { string name; cout << "Введите имя: "; cin >> name; cout << "Привет, " << name << "!" << endl; return 0; }

Работа с файлами

Для работы с файлами используется библиотека <fstream>. Она предоставляет три основных класса:
  • ifstream — чтение из файла (input file stream);
  • ofstream — запись в файл (output file stream);
  • fstream — чтение и запись (file stream).

Запись данных в файл


#include <iostream>
#include <fstream>
using namespace std;

int main() { ofstream file("data.txt"); // открытие файла для записи

if (!file) { cout << "Ошибка при открытии файла!" << endl; return 1; }

file << "Привет, файл!" << endl; file << "Число: " << 42 << endl;

file.close(); // обязательно закрываем файл cout << "Данные записаны!" << endl; return 0; }

Что делает программа

  • Создаёт (или перезаписывает) файл `data.txt` в папке программы.
  • Записывает туда две строки текста.
  • Закрывает файл.

Чтение данных из файла


#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() { ifstream file("data.txt");

if (!file) { cout << "Файл не найден!" << endl; return 1; }

string line; while (getline(file, line)) { cout << line << endl; }

file.close(); return 0; }

Объяснение

  • `getline(file, line)` — читает строку из файла и сохраняет в переменную `line`.
  • Цикл продолжается, пока не достигнут конец файла.

Режимы открытия файлов

Файлы можно открывать в разных режимах:
  • ios::out — запись (удаляет старое содержимое).
  • ios::app — добавление в конец файла.
  • ios::in — чтение.
  • ios::binary — бинарный режим.

Пример: добавление данных


#include <fstream>
#include <string>
using namespace std;

int main() { ofstream file("data.txt", ios::app); // добавление в конец file << "Новая строка" << endl; file.close(); return 0; }

Бинарные файлы

Иногда нужно сохранять данные не в виде текста, а в двоичном формате.

#include <iostream>
#include <fstream>
using namespace std;

int main() { int numbers[3] = {10, 20, 30};

ofstream fout("numbers.bin", ios::binary); fout.write((char*)numbers, sizeof(numbers)); fout.close();

int read[3]; ifstream fin("numbers.bin", ios::binary); fin.read((char*)read, sizeof(read)); fin.close();

cout << read[0] << ", " << read[1] << ", " << read[2] << endl; return 0; }

Как это работает

  • `write()` записывает байты напрямую.
  • `read()` читает байты обратно в массив.
  • Используется приведение `(char*)`, чтобы работать с байтовыми данными.

Проверка ошибок

C++ предоставляет методы для проверки ошибок в работе с файлами:
  • `file.fail()` — ошибка при открытии или записи.
  • `file.eof()` — достигнут конец файла.
  • `file.is_open()` — файл успешно открыт.

Пример


ifstream f("data.txt");
if (!f.is_open()) {
    cout << "Не удалось открыть файл!" << endl;
}

Мини-проект: журнал заметок

Создадим простую программу, которая сохраняет заметки в файл и выводит их.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() { string note; cout << "Введите заметку: "; getline(cin, note);

ofstream file("notes.txt", ios::app); file << note << endl; file.close();

cout << "\nВсе заметки:\n"; ifstream in("notes.txt"); string line; while (getline(in, line)) { cout << "- " << line << endl; } in.close();

return 0; }

Что делает программа

  • Позволяет пользователю ввести новую заметку.
  • Сохраняет её в файл `notes.txt`.
  • Выводит все существующие заметки.

Типичные ошибки новичков

  • Забывают закрыть файл (`file.close()`), из-за чего данные не записываются.
  • Пытаются читать файл, который ещё не существует.
  • Используют `>>` для чтения строк с пробелами — нужно использовать `getline()`.

Советы новичкам

  • Всегда проверяйте, успешно ли открылся файл (`if (!file) ...`).
  • Используйте `ios::app`, чтобы не потерять старые данные.
  • Работая с бинарными файлами, точно указывайте размер данных (`sizeof`).
  • Экспериментируйте: откройте файл в текстовом редакторе и посмотрите, что записалось.

Итоги урока

Теперь вы знаете:
  • Как работать с файлами в C++ через потоки.
  • Как читать и записывать текстовые и бинарные данные.
  • Как проверять ошибки при работе с файлами.
  • Как сделать небольшое приложение, сохраняющее информацию на диск.