Различные статьи по Qt и c++

QFile подробно: открытие, чтение, запись и режимы доступа для начинающих

Введение

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

Концепция

QFile наследует QIODevice — общий интерфейс ввода-вывода Qt, общий с сетевыми сокетами и другими источниками данных. Это значит, что методы read(), write(), readLine() работают одинаково, независимо от того, с файлом вы работаете или, например, с сетевым соединением — освоив QFile, вы уже частично знаете, как пользоваться и другими QIODevice-классами.

Перед любой операцией файл нужно открыть через open(), указав режим: QIODevice::ReadOnly (только чтение), QIODevice::WriteOnly (только запись, существующее содержимое стирается), QIODevice::Append (запись в конец без удаления существующего содержимого), QIODevice::ReadWrite (и чтение, и запись). После работы с файлом обязательно вызывайте close() — либо явно, либо позволяя деструктору QFile сделать это автоматически.

Пример кода: QFile подробно

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

void writeToFile()
{
    QFile file("greeting.txt");

    // WriteOnly стирает старое содержимое файла, если он уже существовал
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Не удалось открыть файл для записи:" << file.errorString();
        return;
    }

    QTextStream out(&file);
    out << "Привет, мир!" << "\n";
    out << "Это вторая строка файла." << "\n";

    file.close();
    qDebug() << "Файл успешно записан";
}

void readFromFile()
{
    QFile file("greeting.txt");

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Не удалось открыть файл для чтения:" << file.errorString();
        return;
    }

    QTextStream in(&file);
    while (!in.atEnd()) {
        QString line = in.readLine();
        qDebug() << "Прочитана строка:" << line;
    }

    file.close();
}

void appendToFile()
{
    QFile file("greeting.txt");

    // Append добавляет в конец, не стирая то, что уже было записано
    if (!file.open(QIODevice::Append | QIODevice::Text)) {
        qDebug() << "Не удалось открыть файл для дозаписи:" << file.errorString();
        return;
    }

    QTextStream out(&file);
    out << "Эта строка добавлена позже.\n";
    file.close();
}

void checkFileExists()
{
    if (QFile::exists("greeting.txt")) {
        qDebug() << "Файл существует";
    } else {
        qDebug() << "Файл не найден";
    }
}

Пояснения к коду

writeToFile() открывает файл в режиме WriteOnly | Text — флаг Text обеспечивает корректную обработку переноса строк на разных платформах (Windows использует \r\n, Linux/macOS — \n, и Qt сам заботится об этом преобразовании). QTextStream, обёрнутый вокруг QFile, даёт удобный способ записи текста через оператор <<, аналогичный std::cout в стандартном C++.

readFromFile() показывает типичный паттерн чтения построчно: in.atEnd() проверяет, достигнут ли конец файла, а in.readLine() читает одну строку за раз. appendToFile() демонстрирует разницу между WriteOnly (стирает файл) и Append (добавляет в конец) — это самая частая путаница у новичков: если вместо Append использовать WriteOnly, весь файл будет перезаписан, и предыдущее содержимое потеряется.

Подводные камни

  • Использование WriteOnly вместо Append, когда нужно добавить данные, а не заменить файл. Это самая частая ошибка новичков — WriteOnly полностью стирает существующее содержимое файла при открытии, даже если вы ничего пока не записали.
  • Забытая проверка результата open(). Если файл не открылся (нет прав доступа, файл занят другим процессом, неверный путь), open() возвращает false — без проверки этого значения дальнейшие операции с файлом будут просто молча ничего не делать.
  • Относительный путь к файлу, зависящий от текущей рабочей директории программы, которая может отличаться при запуске из IDE и при запуске собранного приложения напрямую — для надёжности лучше использовать абсолютный путь, например через QStandardPaths или QCoreApplication::applicationDirPath().
  • Забытый close(). Хотя деструктор QFile сам закрывает файл, явный вызов close() сразу после завершения работы — хорошая привычка, особенно если файл должен быть доступен другим программам сразу после записи, не дожидаясь, когда объект QFile выйдет из области видимости.