QIODevice предоставляет как общую реализацию, так и абстрактный интерфейс для устройств, которые поддерживают чтение и запись блоков данных, таких как QFile, QBuffer и QTcpSocket.
QIODevice является абстрактным и не может быть реализован, но обычно используется интерфейс который он определяет, чтобы обеспечить независимые от устройства функции ввода / вывода.
Перед доступом к устройству необходимо вызвать open(), чтобы установить правильный режим OpenMode (ReadOnly или ReadWrite).
Затем записать используя метод write() или putChar() и выполнить чтение, вызвав read(), readLine() или readAll(). Вызвав close() для завершения и закрытия устройства.
QIODevice различает два типа устройств: устройства с произвольным доступом и последовательные устройства.
Устройства с произвольным доступом поддерживают поиск в произвольных позициях с использованием seek(). Текущая позиция в файле доступна с помощью вызова pos(). QFile и QBuffer являются примерами устройств с произвольным доступом.
Последовательные устройства не поддерживают поиск произвольных позиций. Данные должны быть прочитаны за один проход. Функции pos() и size() не работают для последовательных устройств.
QTcpSocket и QProcess являются примерами последовательных устройств. Для определения типа можно использовать isSequential().
QIODevice вызывает сигнал readyRead(), когда новые данные доступны для чтения. Например, если новые данные поступили в сеть или дополнительные данные добавлены в файл. Если вызвать bytesAvailable(), будет известно количество байтов, которые в данный момент доступны для чтения. Обычно используется bytesAvailable() вместе с сигналом readyRead() при программировании с асинхронными устройствами, такими как QTcpSocket, где фрагменты данных могут поступать в произвольные моменты времени. QIODevice посылает сигнал bytesWritten() каждый раз, когда на устройство записывается полезная нагрузка данных. Используйте bytesToWrite(), чтобы определить текущий объем данных, ожидающих записи.
Некоторые подклассы QIODevice, такие как QTcpSocket и QProcess, являются асинхронными. Это означает, что функции ввода / вывода, такие как write() или read(), всегда возвращаются немедленно, тогда как связь с самим устройством может происходить, когда управление возвращается в цикл обработки событий.
QIODevice предоставляет функции, которые позволяют заставить эти операции выполняться немедленно, блокируя вызывающий поток и не входя в цикл обработки событий. Это позволяет использовать подклассы QIODevice без цикла событий или в отдельном потоке такие как:
waitForReadyRead() — эта функция приостанавливает работу в вызывающем потоке, пока новые данные не станут доступны для чтения.
waitForBytesWritten() — эта функция приостанавливает работу в вызывающем потоке до тех пор, пока одна полезная нагрузка данных не будет записана на устройство.
И другие методы которые имеют реализацию: waitFor..()
Подклассы QIODevice реализуют функции блокировки для специфических для устройства операций.
Некоторые подклассы, такие как QFile и QTcpSocket, реализованы с использованием буфера памяти для промежуточного хранения данных. Это уменьшает количество необходимых устройств, обращающихся к вызовам, которые часто очень медленные.
Буферизация делает такие функции, как getChar() и putChar() быстрыми, поскольку они могут работать с буфером памяти, а не непосредственно с самого устройства. Однако некоторые операции ввода / вывода не работают с буфером. Например, если несколько пользователей открывают одно и то же устройство и читают его символ за символом, они могут закончить тем, что читают одни и те же данные, когда им нужно прочитать каждый отдельный блок. По этой причине QIODevice позволяет обходить любую буферизацию, передавая флаг Unbuffered в методе open().
Входящий поток данных с асинхронного устройства фрагментируется и порции данных могут поступать в произвольные моменты времени. Для обработки неполных чтений структур данных используйте механизм транзакций.
Некоторые последовательные устройства поддерживают связь через несколько каналов. Эти каналы представляют собой отдельные потоки данных, которые имеют свойство независимо упорядоченной доставки. После открытия устройства можно определить количество каналов, вызвав функции readChannelCount() и writeChannelCount(). Для переключения между каналами можно вызвать setCurrentReadChannel() и setCurrentWriteChannel().
QIODevice также предоставляет дополнительные сигналы для обработки асинхронной связи для каждого канала.