Введение
Перед сохранением большого файла или резервной копии разумно проверить, достаточно ли места на диске. Также приложениям часто нужно узнать, на каком разделе расположен тот или иной путь, является ли носитель съёмным, или доступен ли он только для чтения. Для всех этих задач в Qt есть класс QStorageInfo.
Концепция
QStorageInfo предоставляет информацию о точках монтирования файловых систем: общий и свободный объём, тип ФС, метку тома, признаки готовности и доступности только для чтения. Класс работает кросс-платформенно, скрывая различия между Windows (буквы дисков), Linux (точки монтирования) и macOS.
Статический метод QStorageInfo::mountedVolumes() возвращает список всех смонтированных томов в системе, а конструктор QStorageInfo(path) позволяет получить информацию о томе, на котором расположен конкретный путь.
Пример кода: Мониторинг диска и
#include <QStorageInfo>
#include <QDebug>
#include <QDir>
#include <QCoreApplication>
void printStorageInfo(const QStorageInfo &storage)
{
qDebug() << "Точка монтирования:" << storage.rootPath();
qDebug() << " Устройство: " << storage.device();
qDebug() << " Файловая система:" << storage.fileSystemType();
qDebug() << " Метка тома: " << storage.displayName();
qDebug() << " Всего байт: " << storage.bytesTotal();
qDebug() << " Свободно байт: " << storage.bytesAvailable();
qDebug() << " Только чтение: " << storage.isReadOnly();
qDebug() << " Готов: " << storage.isValid() << storage.isReady();
qDebug() << "------------------------------------------";
}
bool hasEnoughSpace(const QString &path, qint64 requiredBytes)
{
QStorageInfo storage(path);
if (!storage.isValid() || !storage.isReady()) {
qWarning() << "Не удалось получить информацию о хранилище для" << path;
return false;
}
qint64 available = storage.bytesAvailable();
qDebug() << "Доступно:" << available / (1024 * 1024) << "МБ,"
<< "требуется:" << requiredBytes / (1024 * 1024) << "МБ";
return available >= requiredBytes;
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
qDebug() << "=== Все смонтированные тома ===";
for (const QStorageInfo &storage : QStorageInfo::mountedVolumes()) {
if (storage.isValid() && storage.isReady())
printStorageInfo(storage);
}
qDebug() << "=== Проверка места перед операцией ===";
QString targetPath = QDir::currentPath();
qint64 needed = 500LL * 1024 * 1024; // 500 МБ
if (hasEnoughSpace(targetPath, needed)) {
qDebug() << "Места достаточно, можно продолжать резервное копирование";
} else {
qWarning() << "Недостаточно свободного места на диске!";
}
return 0;
}
Пояснения к коду
mountedVolumes() возвращает снимок состояния на момент вызова — данные не обновляются автоматически, поэтому для постоянного мониторинга такой вызов нужно периодически повторять (например, по таймеру) либо вызывать refresh() на уже существующем объекте QStorageInfo перед повторным чтением свойств.
bytesAvailable() возвращает количество байт, доступных непривилегированному пользователю — это может отличаться от bytesFree(), который показывает физически свободное место, включая зарезервированное для root/системных нужд место (актуально для Linux/ext4, где часть пространства резервируется).
Подводные камни
bytesFree()противbytesAvailable(). Частая ошибка — использоватьbytesFree()для проверки «можно ли записать файл такого размера». Если приложение работает от обычного пользователя, корректнееbytesAvailable(), так как именно это значение отражает реально доступное пользователю место.
- Устаревшие данные без
refresh(). Если объектQStorageInfoсоздан давно и хранится в памяти (например, как поле класса), его данные о свободном месте не обновляются автоматически. Перед каждой важной проверкой вызывайтеrefresh().
- Сетевые и виртуальные тома. Для сетевых дисков значения
bytesTotal()/bytesAvailable()могут возвращать неточные данные (зависит от сервера) или вызов может выполняться с заметной задержкой — не делайте такие проверки в UI-потоке без необходимости.
- Гонка между проверкой и записью (TOCTOU). Проверка свободного места и последующая запись файла не атомарны — между этими операциями место может закончиться (например, из-за параллельного процесса). Обязательно обрабатывайте ошибки записи (
QFile::error()), даже если предварительная проверка показала достаточный объём.
- Различия в единицах измерения у ОС и пользователя. Производители дисков указывают объём в гигабайтах (10^9 байт), а ОС часто показывает в гибибайтах (2^30 байт) — при выводе пользователю стоит явно указывать единицы измерения и быть последовательным в расчётах.
QStorageInfo — лёгковесный и надёжный способ получать актуальную информацию о дисковом пространстве без необходимости вызывать платформо-зависимые системные API напрямую.
================================================================================