QIODevice Class

本文深入解析Qt中的QIODevice类,探讨其作为I/O设备基接口的重要角色,包括OpenMode、异步操作、随机/顺序设备、信号槽机制及子类应用。了解如何通过继承创建自定义IO设备和处理缓冲与事务机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

QIODevice Class

Public Types

flagsOpenMode
enumOpenModeFlag { NotOpen, ReadOnly, WriteOnly, ReadWrite, Append, …, ExistingOnly }
enum QIODevice::OpenModeFlag
flags QIODevice::OpenMode
  • open()一起用于描述打开设备的模式。它也由openMode()返回。
  • 某些标志,如Unbuffered和Truncate,在一些子类中使用是没有意义的。
    • 其中一些限制是由子类所表示的设备类型所暗示的。
    • 在其他情况下,限制可能是由于实现,或者可能是底层平台强加的;
    • 例如,QTcpSocket不支持Unbuffered模式,并且本机API中的限制阻止QFile在Windows上支持Unbuffered模式。
  • OpenMode类型是QFlags<OpenModeFlag>的类型定义。它存储OpenModeFlag值的OR组合。
  • QIODevice为支持读取和写入数据块(如QFileQBuffer和 QTcpSocket)的设备提供了通用实现和抽象接口。
    • QIODevice是抽象的,不能实例化,但是通常使用它定义的接口来提供与设备无关的I/O特性。
    • 例如,Qt的XML类操作一个QIODevice指针,允许它们与各种设备(如文件和缓冲区)一起使用。
  • 在访问设备之前,必须调用open()来设置正确的OpenMode(例如ReadOnly或ReadWrite)。
    • 然后,您可以使用write()或putChar()向设备进行写入,并通过调用read()、readLine()或readAll()进行读取。当你用完这个设备时,调用close()。
  • QIODevice区分了两种类型的设备 :随机访问设备顺序设备
    • 随机访问设备支持使用seek()查找到任意位置。通过调用pos()可以获得文件中的当前位置。QFile和QBuffer是随机访问设备的例子。
    • 顺序设备不支持寻找任意位置。数据必须一次读取。函数pos()和size()不适用于顺序设备。QTcpSocket和QProcess是顺序设备的例子。
    • 可以使用isSequential()来确定设备的类型。
  • 有新的数据可供读取时,QIODevice发出readyRead(); 例如,如果新的数据已经到达网络上,或者附加的数据被附加到正在读取的文件中。
    • 可以调用bytesAvailable()来确定当前可读取的字节数
    • 在使用异步设备(如QTcpSocket)编程时,通常使用bytesAvailable()和readyRead()信号,在异步设备中,数据片段可以到达任意时间点。
    • QIODevice在每次将数据有效负载写入设备时发出bytesWritten()信号。使用 bytesToWrite()确定当前等待写入的数据量
  • QIODevice的某些子类,如QTcpSocket和QProcess,是异步的。
    • 这意味着像write()或read()这样的I/O函数总是立即返回,而当控制返回到事件循环时,与设备本身的通信可能会发生。
    • QIODevice提供的函数允许强制立即执行这些操作,同时阻塞调用线程并且不进入事件循环。这允许在没有事件循环的情况下使用QIODevice的子类,或者在单独的线程中使用:
      • waitForReadyRead()——该函数在调用线程中暂停操作,直到有新的数据可供读取。
      • waitForBytesWritten()——该函数在调用线程中暂停操作,直到数据的一个有效负载被写入设备。
      • waitFor....()——QIODevice的子类为设备特定的操作实现阻塞函数。例如,QProcess有一个名为waitForStarted()的函数,它会暂停调用线程中的操作,直到进程启动。
  • 从主GUI线程调用这些函数可能会导致用户界面冻结。例子:
QProcess gzip;
gzip.start("gzip", QStringList() << "-c");
if (!gzip.waitForStarted())
    return false;

gzip.write("uncompressed data");

QByteArray compressed;
while (gzip.waitForReadyRead())
    compressed += gzip.readAll();
  • 通过继承QIODevice的子类,您可以为自己的I/O设备提供相同的接口。
    • QIODevice的子类只需要实现受保护的readData()writeData()函数。
    • QIODevice使用这些函数来实现它的所有便利函数,比如getChar()、readLine()和write()。
    • QIODevice还为处理访问控制,因此如果调用writeData(),您\可以安全地假设设备是在写模式下打开的。
  • 一些子类,如QFile和QTcpSocket,是使用用于中间存储数据的内存缓冲区来实现的。
    • 这减少了所需的设备访问呼叫的数量,这通常是非常缓慢的。
    • 缓冲使getChar()和putChar()这样的函数速度更快,因为它们可以在内存缓冲区上操作,而不是直接在设备本身上操作。
    • 但是,某些I/O操作不能很好地与缓冲区一起工作。例如,如果几个用户打开相同的设备并逐个字符地读取它,他们可能最终会读取相同的数据,而他们本打算读取单独的块。
    • 出于这个原因,QIODevice允许通过将Unbuffered标志传递给open()来绕过任何缓冲。当继承QIODevice的子类时,请记得在设备以Unbuffered模式打开时绕过任何可能使用的缓冲区。
  • 通常,来自异步设备的传入数据流是分段的,数据块可以到达任意时间点。要处理数据结构的不完整读取,可以使用QIODevice实现的事务机制。有关详细信息,请参阅startTransaction()和相关函数。
  • 一些顺序设备支持通过多个通道进行通信。
    • 这些通道表示具有独立排序传递属性的独立数据流
    • 一旦设备被打开,可以通过调用readChannelCount()和writeChannelCount()函数来确定通道的数量。
    • 要在通道之间切换,分别调用setCurrentReadChannel()和setCurrentWriteChannel()。
    • QIODevice还提供了额外的信号来处理每个通道的异步通信。
  • 参考:QBufferQFile, 和QTcpSocket.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值