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

QFileInfo на практике: примеры работы с файлами и каталогами

обновлено 179 просмотров

Введение

Класс QFileInfo предоставляет сведения о файле или каталоге: имя, расширение, размер, даты, права доступа. Подробный справочник по его методам есть в статье QFileInfo: получение информации о файлах и каталогах. Здесь же собраны практические примеры QFileInfo для повседневных задач: проверка файла перед открытием, обход каталога, сортировка по дате, поиск самого нового файла, подсчёт размера папки и формирование имён файлов.

Простые примеры QFileInfo: свойства файла

#include <QFileInfo>
#include <QDebug>

QFileInfo info("example.txt");
qDebug() << "Имя файла:" << info.fileName();
qDebug() << "Путь:" << info.absolutePath();
qDebug() << "Полный путь:" << info.absoluteFilePath();
qDebug() << "Размер (байт):" << info.size();
qDebug() << "Расширение:" << info.suffix();
qDebug() << "Изменён:" << info.lastModified().toString("dd.MM.yyyy hh:mm");

Проверка файла перед открытием

Прежде чем открывать файл, полезно убедиться, что он существует, является именно файлом и доступен для чтения. Так пользователь получит понятное сообщение вместо общей ошибки:

bool checkInputFile(const QString &path, QString *error)
{
    QFileInfo info(path);
    if (!info.exists())     { *error = "Файл не найден";            return false; }
    if (!info.isFile())     { *error = "Указан каталог, а не файл"; return false; }
    if (!info.isReadable()) { *error = "Нет прав на чтение";        return false; }
    if (info.size() == 0)   { *error = "Файл пустой";               return false; }
    return true;
}

Список файлов в каталоге

Метод QDir::entryInfoList() сразу возвращает список объектов QFileInfo. Фильтры позволяют выбрать только нужные файлы:

#include <QDir>

QDir dir("C:/photos");
QFileInfoList files = dir.entryInfoList(
    {"*.jpg", "*.png"},               // фильтр по маске
    QDir::Files | QDir::NoDotAndDotDot,
    QDir::Time);                      // сортировка: сначала новые

for (const QFileInfo &fi : files)
    qDebug() << fi.fileName() << fi.size() << fi.lastModified();

Вместо QDir::Time можно указать QDir::Size (по размеру) или QDir::Name (по имени). Флаг QDir::Reversed меняет порядок на обратный.

Самый новый файл в папке

Частая задача — найти последний созданный лог или резервную копию:

QFileInfo newestFile(const QString &dirPath, const QString &mask)
{
    QDir dir(dirPath);
    QFileInfoList list = dir.entryInfoList({mask}, QDir::Files, QDir::Time);
    return list.isEmpty() ? QFileInfo() : list.first();
}

QFileInfo last = newestFile("logs", "*.log");
if (last.exists())
    qDebug() << "Последний лог:" << last.fileName();

Размер папки

Метод size() для каталога не возвращает объём его содержимого. Чтобы посчитать размер папки, нужно обойти все файлы, включая вложенные каталоги. Для этого удобен QDirIterator:

#include <QDirIterator>
#include <QLocale>

qint64 folderSize(const QString &path)
{
    qint64 total = 0;
    QDirIterator it(path, QDir::Files | QDir::Hidden, QDirIterator::Subdirectories);
    while (it.hasNext()) {
        it.next();
        total += it.fileInfo().size();
    }
    return total;
}

qDebug() << QLocale().formattedDataSize(folderSize("C:/projects"));

Метод QLocale::formattedDataSize() превращает байты в удобную строку вида «1,5 ГБ».

Формирование имён файлов

QFileInfo удобно использовать, чтобы построить новое имя на основе существующего. Например, создать резервную копию с тем же именем, но другим расширением:

QFileInfo src("/data/config.json");
QString backup = src.absolutePath() + "/" + src.completeBaseName() + ".bak";
// /data/config.bak

А так можно получить свободное имя, если файл уже существует, — по схеме «имя (1).расширение»:

QString uniqueFileName(const QString &path)
{
    QFileInfo info(path);
    if (!info.exists())
        return path;

    const QString base = info.absolutePath() + "/" + info.completeBaseName();
    const QString ext = info.suffix().isEmpty() ? "" : "." + info.suffix();

    for (int i = 1; ; ++i) {
        QString candidate = QString("%1 (%2)%3").arg(base).arg(i).arg(ext);
        if (!QFileInfo::exists(candidate))
            return candidate;
    }
}

Удаление старых файлов

Чтобы логи не занимали весь диск, старые файлы можно удалять по дате изменения:

void removeOldLogs(const QString &dirPath, int days)
{
    const QDateTime border = QDateTime::currentDateTime().addDays(-days);
    QDir dir(dirPath);
    for (const QFileInfo &fi : dir.entryInfoList({"*.log"}, QDir::Files)) {
        if (fi.lastModified() < border)
            QFile::remove(fi.absoluteFilePath());
    }
}

Частые ошибки

  • Использовать size() для папки. Метод не считает содержимое. Нужен обход, как в примере выше.
  • Забывать про refresh(). QFileInfo запоминает данные о файле. Если файл изменился, обновите объект.
  • Путать suffix() и completeSuffix(). Для archive.tar.gz первый вернёт «gz», второй — «tar.gz».
  • Полагаться на birthTime(). Не все файловые системы хранят дату создания. Проверяйте результат через isValid().
  • Строить пути вручную через «\». Используйте прямой слеш «/»: Qt сам преобразует его в нужный формат на любой платформе.
  • Проверять существование и сразу открывать файл. Между проверкой и открытием файл может исчезнуть. Всегда обрабатывайте ошибку open().

Эти мелочи легко упустить. Но именно они чаще всего приводят к странному поведению программы на компьютере пользователя.

Полезные методы QFileInfo

МетодНазначение
exists()Существует ли файл
isFile(), isDir()Проверка типа
fileName()Имя файла с расширением
completeBaseName()Имя без последнего расширения
absoluteFilePath()Полный путь
size()Размер файла в байтах
suffix()Расширение
birthTime()Время создания
lastModified()Время изменения
isReadable(), isWritable()Права доступа

Заключение

Эти примеры QFileInfo покрывают большинство повседневных задач: проверку входных файлов, обход и сортировку каталогов, подсчёт размера и работу с именами. В связке с QDir и QDirIterator класс становится удобным инструментом для файловых менеджеров, систем логирования, архиваторов и утилит резервного копирования. Полный список методов смотрите в справочнике по QFileInfo.