Готовые методы реализаций

QFile — работа с файлами в Qt C++: чтение, запись, копирование

обновлено 1 182 просмотров

Введение

Почти любое приложение работает с файлами: читает настройки, сохраняет документы, пишет логи. В Qt основной класс для этого — QFile. Он даёт единый интерфейс для работы с файлами на всех платформах: с его помощью можно читать и записывать данные, копировать, переименовывать и удалять файлы, проверять их существование. В статье разберём основные операции с QFile на примерах, а также обработку ошибок и безопасную запись.

Подключение QFile

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

#include <QFile>
#include <QTextStream>
#include <QDebug>

QFile наследуется от QIODevice. Поэтому с ним работают все классы Qt, которые принимают устройство ввода-вывода: QTextStream для текста, QDataStream для двоичных данных, QXmlStreamReader для XML.

Чтение текста из файла

QFile file("example.txt");
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
    QTextStream in(&file);
    QString content = in.readAll();
    qDebug() << content;
    file.close();
} else {
    qDebug() << "Не удалось открыть файл:" << file.errorString();
}

Флаг QIODevice::Text преобразует окончания строк: при чтении в Windows символы \r\n превращаются в \n. Метод readAll() подходит для небольших файлов. Большие файлы лучше читать построчно:

QFile file("big.log");
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
    while (!file.atEnd()) {
        QByteArray line = file.readLine();
        // обработка строки
    }
}

Запись текста в файл

QFile file("output.txt");
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
    QTextStream out(&file);
    out << "Привет, мир!\n";
    file.close();
}

Режим WriteOnly создаёт файл, если его нет, и перезаписывает содержимое, если файл уже существует.

Добавление текста (Append)

Чтобы дописать данные в конец файла, не стирая старые, используйте флаг Append. Так обычно ведут логи:

QFile file("log.txt");
if (file.open(QIODevice::Append | QIODevice::Text)) {
    QTextStream out(&file);
    out << "Новая запись: " << QDateTime::currentDateTime().toString() << "\n";
    file.close();
}

Чтение и запись двоичных данных

Если файл не текстовый, читайте его без флага Text. Методы read() и write() работают с QByteArray:

QFile file("image.png");
if (file.open(QIODevice::ReadOnly)) {
    QByteArray header = file.read(8);      // первые 8 байт
    qDebug() << "Размер файла:" << file.size() << "байт";
}

Для структурированных двоичных данных удобнее использовать QDataStream поверх QFile.

Проверка существования и удаление

QFile file("old_data.txt");
if (file.exists()) {
    file.remove();
    qDebug() << "Файл удалён.";
} else {
    qDebug() << "Файл не найден.";
}

Есть и статические версии этих методов: QFile::exists("path") и QFile::remove("path"). Объект создавать не нужно.

Копирование и переименование файла

if (QFile::copy("source.txt", "backup.txt")) {
    qDebug() << "Файл скопирован.";
} else {
    qDebug() << "Ошибка при копировании.";
}

QFile::rename("draft.txt", "final.txt");

Обратите внимание: QFile::copy() не перезаписывает существующий файл. Если файл с таким именем уже есть, метод вернёт false. В этом случае сначала удалите старый файл. Метод rename() ведёт себя так же.

Полезные флаги QIODevice

  • QIODevice::ReadOnly — только для чтения;
  • QIODevice::WriteOnly — только для записи;
  • QIODevice::ReadWrite — чтение и запись;
  • QIODevice::Append — запись в конец файла;
  • QIODevice::Truncate — очистить файл при открытии;
  • QIODevice::Text — текстовый режим с преобразованием окончаний строк;
  • QIODevice::NewOnly — открыть, только если файл ещё не существует (Qt 5.11+).

Обработка ошибок

Метод open() возвращает false, если файл открыть не удалось. Причину покажет метод errorString(), а код ошибки — метод error(). Частые причины: файл не существует, нет прав доступа, файл занят другой программой или путь указан относительно не того каталога. Относительные пути отсчитываются от текущего рабочего каталога программы, а он не всегда совпадает с папкой, где лежит exe-файл. Для надёжности стройте пути через QCoreApplication::applicationDirPath() или QStandardPaths.

Закрывать ли файл вручную

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

Безопасная запись: QSaveFile

Если программа аварийно завершится во время записи, файл может остаться повреждённым. Класс QSaveFile решает эту проблему: он пишет данные во временный файл и заменяет оригинал только после успешного commit():

#include <QSaveFile>

QSaveFile file("settings.json");
if (file.open(QIODevice::WriteOnly)) {
    file.write(jsonData);
    file.commit();   // оригинал заменяется только здесь
}

Файлы из ресурсов

QFile умеет читать файлы, встроенные в приложение через систему ресурсов Qt. Путь к ним начинается с двоеточия, например ":/data/config.json". Такие файлы доступны только для чтения.

Заключение

Класс QFile — основа любой работы с файлами в Qt. Он открывает файлы в разных режимах, читает и пишет текст и двоичные данные, копирует, переименовывает и удаляет файлы. Всегда проверяйте результат open() и используйте errorString() для диагностики. Для важных данных выбирайте QSaveFile. QFile отлично работает в связке с QTextStream и QFileInfo.