Работа с файлами, директориями и потоками ввода/вывода в Qt


Редко встречается приложение, которое не обращается к файлам. Работа с директориями (папками, в терминологии ОС Windows) и файлами — это та область, в которой не все операции являются платформонезависимыми, поэтому Qt предоставляет свою собственную поддержку этих операций, состоящую из следующих классов:

  • QDir — для работы с директориями;
  • QFile — для работы с файлами;
  • QFileInfо — для получения файловой информации;
  • QIODevice — абстрактный класс для ввода/вывода;
  • QBuffer — для эмуляции файлов в памяти компьютера.

Ввод/вывод. Класс QIODevice

QIODevice — это абстрактный класс, обобщающий устройство ввода/вывода, который содержит виртуальные методы для открытия и закрытия устройства ввода/вывода, а также для чтения и записи блоков данных или отдельных символов.

Реализация конкретного устройства происходит в унаследованных классах.

В Qt есть четыре класса, наследующие класс QIODevice:

  • QFile — класс для проведения операций с файлами;
  • QBuffer — позволяет записывать и считывать данные в массив QByteArray, как будто бы это устройство или файл;
  • QAbstractSocket — базовый класс для сетевой коммуникации посредством сокетов.
  • QProcess — этот класс предоставляет возможность запуска процессов с дополнительными аргументами и позволяет обмениваться информацией с этими процессами посредством методов, определенных в QIODevice.

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

  • QIODevice::NotOpen — устройство не открыто (это значение не имеет смысла передавать в метод open());
  • QIODevice::ReadOnly — открытие устройства только для чтения данных;
  • QIODevice::writeOnly — открытие устройства только для записи данных;
  • QIODevice::ReadWrite — открытие устройства для чтения и записи данных (то же, что и IO_ReadOnly | IO_WriteOnly);
  • QIODevice::Append — открытие устройства для добавления данных;
  • QIODevice::Unbuffered — открытие для непосредственного доступа к данным, в обход промежуточных буферов чтения и записи;
  • QIODevice::Text — применяются преобразования символов переноса строки в зависимости от платформы. Для ОС Windows, например — \r\n, а для MacOS X и UNIX — /r;
  • QIODevice::Truncate — все данные устройства, по возможности, должны быть удалены при открытии.

Для того чтобы в любой момент времени исполнения программы узнать, в каком из режимов было открыто устройство, нужно вызвать метод openMode().

Считывать и записывать данные можно с помощью методов read() и write() соответственно. Для чтения всех данных сразу определен метод readAll(), который возвращает их в объекте типа QByteArray. Строку или символ можно прочитать методами readLine() и getChar() соответственно.

В классе QIODevice определен метод для смены текущего положения seek(). Получить текущее положение можно вызовом метода pos(). Но не забывайте, что эти методы применимы только для прямого доступа к данным. При последовательном доступе, каким является сетевое соединение, они теряют смысл. Более того, в этом случае теряет смысл и метод size(), возвращающий размер данных устройства. Все эти операции применимы только для QFile, QBuffer и QTemporaryFile.

Для создания собственного класса устройства ввода/вывода, для которого Qt не предоставляет поддержки, необходимо унаследовать класс QIODevice и реализовать в нем методы readData() и writeData(). В большинстве случаев может потребоваться перезаписать методы open(), close() и atEnd().

Благодаря интерфейсу класса QIODevice можно работать со всеми устройствами одинаково, при этом не имеет значения, является ли устройство файлом, буфером или другим устройством. Выведем на консоль данные из любого устройства.


void print(QIODevice *pdev)
{
    char ch;
    QString str;
    pdev->open(QIODevice::ReadOnly);
    for (; !pdev->atEnd();)
    {
        pdev->getChar(&ch);
        str += ch;
    }
    pdev->close();
    qDebug() << str;
}

Класс QIODevice предоставляет ряд методов, с помощью которых можно получить информацию об устройстве ввода/вывода. Например, одни устройства могут только записывать информацию, другие — только считывать, а третьи способны делать и то, и другое. Чтобы узнать об этом, следует воспользоваться методами isReadable() и isWriteable().

Читать далее: Работа с файлами. Класс QFile