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++ через потоки.
- Как читать и записывать текстовые и бинарные данные.
- Как проверять ошибки при работе с файлами.
- Как сделать небольшое приложение, сохраняющее информацию на диск.