QFile и QThreadPool: Отзывчивое чтение файлов

QFile и QThreadPool: Отзывчивое чтение файлов

Прочитать файл с диска в Qt предельно просто (без учета обработки ошибок):

Но этот код работает приемлемо лишь для относительно небольших файлов. А что если размер файла переваливает за пару сотню Мб? В этом случае приведенная выше реализация заметно подвесит графический интерфейс пользователя. Исправить ситуацию нам помогут потоки в Qt.

Планирование

Воспользуемся реализацией потока в стиле QThreadPool на основе задачи QRunnable. Создадим простой класс LargeFileReaderTask, который умеет:

  1. Выполнять последовательное чтение файла блок за блоком с помощью QFile;
  2. Сообщать о ходе выполнения загрузки (сколько получено байтов от общего числа);
  3. Обеспечить возможность отмены чтения файла;
  4. Возвращать окончательный результат (прочитанные данные файла).

Реализация

Начинаем с интерфейса класса LargeFileReaderTask. Файл largefilereadertask.h:

Входными данными задачи являются имя файла и размер блока, который может быть прочитан за один шаг. Чем размер блока для чтения меньше, тем быстрее мы можем среагировать на запрос пользователя об остановке. Однако это добавляет накладные расходы и увеличивает суммарное время чтения. В качестве компромисса используем размер в 10 000 Кб.

Обратите внимание на поле m_cancelledMarker типа QAtomicInt. Оно понадобится нам для синхронизации действия отмены чтения. Подробнее об атомарных типах мы поговорим в другой раз.

Теперь реализация. Файл largefilereadertask.cpp:

Само чтение укладывается в функции run(), и заключается в строках:

Так мы делаем в цикле до тех пор, пока:

Т.е. пока прочитанный блок не пустой.

Интеграция в GUI-приложение

С помощью LargeFileReaderTask можно создать приложение.

Оно позволяет:

  1. Выбрать и начать чтение любого файла по кнопке Open;
  2. Отображать ход выполнения операции чтения с помощью QProgressBar;
  3. Отменить чтение файла по кнопке Cancel.

Файл largefilereadingdemowidget.h:

И реализация из largefilereadingdemowidget.cpp:

Замечание

Не забывайте, что размер оперативной памяти ограничен. А также имеется ее фрагментация. Поэтому непрерывные блоки больших размеров может быть невозможно уместить в RAM в той или иной ситуации. В связи с этим слишком большие файлы в память грузить не рекомендуется. Лучше обрабатывать их поточными алгоритмами «на лету».

Понравилась статья? Поделиться с друзьями:
Добавить комментарий