Введение
Работа с файловой системой — одна из ключевых задач в любом прикладном программировании. В C++ существует два основных подхода: классический (с использованием библиотеки <fstream>) и современный (с использованием библиотеки <filesystem>, доступной начиная со стандарта C++17). В этой статье мы на практических примерах разберем, как читать и записывать файлы, создавать и удалять директории, а также проверять существование файлов.
Материал будет полезен как новичкам, только осваивающим C++, так и опытным разработчикам, которые хотят освежить знания о современных возможностях языка.
1. Чтение и запись текстовых файлов с помощью fstream
Библиотека <fstream> предоставляет классы для работы с файлами: ifstream (чтение), ofstream (запись) и fstream (чтение и запись).
1.1. Запись данных в файл
Для записи в файл используем объект ofstream. Если файл не существует, он будет создан. Если существует — содержимое будет перезаписано (по умолчанию).
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ofstream outFile("example.txt");
if (!outFile.is_open()) {
std::cerr << "Ошибка открытия файла!" << std::endl;
return 1;
}
outFile << "Привет, мир!" << std::endl;
outFile << "Это вторая строка." << std::endl;
outFile.close();
std::cout << "Данные записаны." << std::endl;
return 0;
}
Обратите внимание: мы всегда проверяем, удалось ли открыть файл, и закрываем его после использования.
1.2. Чтение данных из файла
Для чтения используем ifstream. Самый простой способ — читать построчно с помощью std::getline.
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream inFile("example.txt");
if (!inFile.is_open()) {
std::cerr << "Ошибка открытия файла!" << std::endl;
return 1;
}
std::string line;
while (std::getline(inFile, line)) {
std::cout << line << std::endl;
}
inFile.close();
return 0;
}
Этот метод удобен тем, что автоматически обрабатывает конец файла и не требует дополнительных проверок.
1.3. Режимы открытия файла
Вы можете комбинировать флаги для управления режимом открытия. Например, чтобы добавить данные в конец файла (режим аппенда), используйте флаг std::ios::app:
std::ofstream outFile("example.txt", std::ios::app);
outFile << "Дополнительная строка." << std::endl;
outFile.close();
Другие полезные флаги: std::ios::binary (бинарный режим), std::ios::trunc (очистка файла при открытии).
2. Современная работа с файловой системой (C++17 и filesystem)
Библиотека <filesystem> значительно упрощает манипуляции с файлами и папками. Все функции находятся в пространстве имен std::filesystem.
2.1. Проверка существования файла или директории
Функция exists() возвращает true, если объект существует:
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
std::string path = "example.txt";
if (fs::exists(path)) {
std::cout << "Файл существует." << std::endl;
} else {
std::cout << "Файл не найден." << std::endl;
}
return 0;
}
2.2. Создание и удаление директорий
Для создания папки используйте create_directory(). Для удаления — remove() или remove_all() (рекурсивное удаление).
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
// Создание директории
if (fs::create_directory("test_folder")) {
std::cout << "Папка создана." << std::endl;
} else {
std::cout << "Не удалось создать папку." << std::endl;
}
// Удаление директории (только пустой)
if (fs::remove("test_folder")) {
std::cout << "Папка удалена." << std::endl;
}
// Рекурсивное удаление
// fs::remove_all("test_folder"); // удалит папку со всем содержимым
return 0;
}
Обратите внимание: create_directory создает только одну директорию. Для создания вложенных папок используйте create_directories() (во множественном числе).
2.3. Копирование и перемещение файлов
Библиотека filesystem предоставляет удобные функции для копирования и перемещения:
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
// Копирование файла
fs::copy("source.txt", "destination.txt");
std::cout << "Файл скопирован." << std::endl;
// Перемещение (переименование) файла
fs::rename("old_name.txt", "new_name.txt");
std::cout << "Файл перемещен/переименован." << std::endl;
return 0;
}
При копировании можно указать опции, например, fs::copy_options::overwrite_existing для перезаписи существующего файла.
3. Практический пример: менеджер заметок
Давайте объединим полученные знания и напишем простую программу для управления текстовыми заметками. Программа будет создавать, читать и удалять заметки (фай