欢迎加入QQ群:853840665,一块学习分享资料
PyQt5类翻译、示例学习 class-learning
描述
QIODevice类是Qt中所有I/O设备的基本接口类。
QIODevice为支持数据块(如QFile、QBuffer和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()信号一起使用,在QTcpSocket这样的异步设备中,数据片段可以及时到达任意点。每次将数据负载写入设备时,QIODevice都会发出bytesWritten()信号。使用bytesToWrite()确定当前等待写入的数据量。
QIODevice的某些子类(如QTcpSocket和QProcess)是异步的。这意味着诸如write()或read()这样的I/O函数总是立即返回,而当控制返回到事件循环时,与设备本身的通信可能发生。QIODevice提供的函数允许您强制立即执行这些操作,同时阻塞调用线程,并且不需要进入事件循环。这使得QIODevice子类可以在没有事件循环的情况下使用,或者在单独的线程中使用。
waitForReadyRead()-此函数将挂起调用线程中的操作,直到有新的数据可供读取。
waitForBytesWritten() - 此函数将挂起调用线程中的操作,直到将一个数据有效负载写入设备为止。
waitFor…() -QIODevice的子类为特定于设备的操作实现阻塞功能。例如,QProcess有一个名为waitForStarted() 的函数,它将挂起调用线程中的操作,直到进程启动。
从主GUI线程调用这些函数可能会导致用户界面冻结。例子:
gzip = QProcess()
gzip.start("gzip", "-c")
if !gzip.waitForStarted():
return false
gzip.write("uncompressed data")
compressed = QByteArray()
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允许您通过将关缓冲标志传递给open()来绕过任何缓冲。当子类化QIODevice时,请记住,当设备在非缓冲模式下打开时,要绕过您可能使用的任何缓冲区。
通常,来自异步设备的传入数据流是片段化的,数据块可以在任意时间点到达。为了处理不完整的数据结构读取,可以使用QIODevice实现的事务机制。有关详细信息,请参见startTransaction() 和相关函数。
一些连续的设备支持通过多个通道进行通信。这些通道表示独立的数据流,这些数据流具有独立的顺序传递属性。一旦设备被打开,您可以通过调用readChannelCount() 和writeChannelCount() 函数来确定通道的数量。要在通道之间切换,分别调用setCurrentReadChannel() 和setCurrentWriteChannel() 。QIODevice还提供了额外的信号来处理每个通道上的异步通信。
Public Types
enum QIODevice::OpenModeFlag
flags QIODevice::OpenMode
这个enum与open() 一起使用,描述设备打开的模式。它也由openMode() 返回。
Constant | Value | Description |
---|---|---|
QIODevice::NotOpen | 0x0000 | 设备没有打开 |
QIODevice::ReadOnly | 0x0001 | 只读 |
QIODevice::WriteOnly | 0x0002 | 该设备可用于书写。注意,对于文件系统子类(例如QFile),此模式意味着Truncate,除非与ReadOnly、Append或NewOnly组合。 |
QIODevice::ReadWrite | ReadOnly|WriteOnly | 设备打开可用于读写 |
QIODevice::Append | 0x0004 | 设备以附加模式打开,以便将所有数据写入文件末尾。 |
QIODevice::Truncate | 0x0008 | 如果可能,设备在打开之前被截断。设备的所有早期内容都丢失了。 |
QIODevice::Text | 0x0010 | 读取时,行尾终止符被翻译为’\n’。在写入时,行尾终止符被转换为本地编码,例如Win32中的’\r\n’。 |
QIODevice::Unbuffered | 0x0020 | 禁用缓冲 |
QIODevice::NewOnly | 0x0040 | 如果要打开的文件已经存在,则失败。只有在文件不存在时才创建并打开它。操作系统保证您是惟一创建和打开文件的人。注意,这种模式意味着只写,并且允许将它与读写结合。此标志当前仅影响QFile。其他类将来可能会使用这个标志,但是在此之前,在QFile之外的任何类中使用这个标志可能会导致未定义的行为。(因为Qt 5.11) |
QIODevice::ExistingOnly | 0x0080 | 如果要打开的文件不存在,则失败。此标志必须与ReadOnly、WriteOnly或ReadWrite一起指定。注意,仅在ReadOnly中使用这个标志是多余的,因为当文件不存在时ReadOnly已经失败了。此标志当前仅影响QFile。其他类将来可能会使用这个标志,但是在此之前,在QFile之外的任何类中使用这个标志可能会导致未定义的行为。(因为Qt 5.11) |
某些标记(Unbuffered和Truncate)与某些子类一起使用时毫无意义。这些限制中的一些是由子类表示的设备类型所暗示的。在其他情况下,限制可能是由于实现,或可能是由底层平台强加的;例如,QTcpSocket不支持非缓冲模式,并且本机API中的限制阻止QFile在Windows上支持非缓冲模式。
OpenMode类型是QFlags的类型定义。它存储OpenModeFlag值的一个或多个组合。
Public Functions
QIODevice(QObject *parent)
使用给定的父对象构造一个QIODevice对象。
QIODevice()
构造一个QIODevice对象。
virtual ~QIODevice()
析构函数是虚拟的,而QIODevice是一个抽象基类。这个析构函数不调用close(),但是子类析构函数可能调用。如果您有疑问,请在销毁QIODevice之前调用close()。
virtual bool atEnd() const
如果当前读写位置在设备的末端(即设备上没有更多的数据可供读取),则返回true;否则返回false。
对于某些设备,即使还有更多数据可供读取,atEnd() 也可以返回true。这种特殊情况只适用于直接响应您调用read() 而生成数据的设备(例如,Unix和macOS上的/dev或/proc文件,或所有平台上的控制台输入/ stdin)。
virtual qint64 bytesAvailable()
返回可用于读取的字节数。此函数通常与顺序设备一起使用,以在读取之前确定缓冲区中要分配的字节数。
为了包含QIODevice的缓冲区大小,重新实现该函数的子类必须调用基实现。例子:
def bytesAvailable(self):
return buffer.size() + QIODevice.bytesAvailable()
virtual qint64 bytesToWrite()
对于缓冲设备,此函数返回等待写入的字节数。对于没有缓冲区的设备,此函数返回0。
为了包含QIODevice的缓冲区大小,重新实现该函数的子类必须调用基实现。
virtual bool canReadLine()
如果可以从设备读取完整的数据行,则返回true;否则返回false。
注意,没有缓冲的设备,无法确定什么可以读取,总是返回false。
这个函数通常与readyRead() 信号一起调用。
为了包含QIODevice缓冲区的内容,重新实现这个函数的子类必须调用基实现。
例如:
def canReadLine(self):
return buffer.contains('\n') || QIODevice::canReadLine();
virtual void close()
首先发出aboutToClose(),然后关闭设备并将其OpenMode设置为NotOpen。错误字符串也被重置。
void commitTransaction()
完成一个读事务。
对于顺序设备,事务期间在内部缓冲区中记录的所有数据都将被丢弃。
这个函数是在Qt 5.7中引入的。
int currentReadChannel()
返回当前读取通道的索引。
这个函数是在Qt 5.7中引入的。
int currentWriteChannel()
返回当前写通道的索引。
这个函数是在Qt 5.7中引入的。
QString errorString()
返回最近发生的设备错误的可读描述。
bool getChar(char *c)
从设备中读取一个字符并将其存储在c中。如果c为0,该字符将被丢弃。成功才有真回True;否则返回False。
bool isOpen()
如果设备处于打开状态,则返回true;否则返回false。一个设备是打开的,如果它可以读取和/或写入。默认情况下,如果openMode() 返回NotOpen,则此函数返回false。
bool isReadable()
如果可以从设备读取数据,则返回true;否则返回false。使用bytesAvailable() 确定可以读取多少字节。
这是一个方便的函数,它检查设备的OpenMode是否包含ReadOnly标志。
virtual bool isSequential()
如果该设备是连续的,则返回true;否则返回false。
与随机访问设备相反,顺序设备没有开始、结束、大小或当前位置的概念,并且它们不支持查找。您只能在设备报告数据可用时从设备读取数据。连续设备最常见的例子是网络套接字。在Unix上,像/dev/zero和fifo管道这样的特殊文件是连续的。
bool isTextModeEnabled()
如果启用文本标志,则返回true;否则返回false。
bool isTransactionStarted()
如果一个事务正在设备上进行,则返回true,否则返回false。
这个函数是在Qt 5.7中引入的。
bool isWritable()
如果数据可以写入设备,则返回true;否则返回false。
这是一个方便的函数,它检查设备的OpenMode是否包含WriteOnly标志。
virtual bool open(QIODevice::OpenMode mode)
打开设备并将其OpenMode设置为mode。如果成功返回true;否则返回false。这个函数应该从open()的任何重新实现或打开设备的其他函数中调用。
QIODevice::OpenMode openMode()
返回设备被打开的模式;即只读或只写。
qint64 peek(char *data, qint64 maxSize)
从设备中读取最多的maxSize字节到数据,没有副作用。(如果在peek()之后调用read(),则会得到相同的数据。)返回读取的字节数。如果发生错误,例如试图查看在WriteOnly模式下打开的设备时,此函数将返回-1。
当没有更多数据可供读取时,返回0。
例如:
def isExeFile(QFile *file)
if (file->peek(buf, 2) == 2):
return (buf[0] == 'M' && buf[1] == 'Z')
return false
这个函数是在Qt 4.1中引入的。
QByteArray peek(qint64 maxSize)
这是一个重载函数。
从设备中查找最多的maxSize字节,返回QByteArray类型数据。
def isExeFile(file: QFile)
return file.peek(2) == "MZ";
该函数没有报告错误的方法;返回None可能意味着当前没有数据可供窥视,或者发生了错误。
virtual qint64 pos()
对于随机访问设备,此函数返回数据写入或读取的位置。对于顺序设备或关闭的设备,如果没有“当前位置”的概念,则返回0。
设备的当前读/写位置由QIODevice内部维护,因此无需重新实现该功能。当子类化QIODevice时,使用QIODevice::seek()来通知QIODevice设备位置的变化。
bool putChar(char c)
将字符c写入设备。成功返回True;否则返回False。
qint64 read(char *data, qint64 maxSize)
从设备中读取最多maxSize字节的数据,并返回读取的字节数。如果发生错误,例如试图从在WriteOnly模式下打开的设备读取数据时,此函数将返回-1。
当没有更多数据可供读取时,返回0。但是,读过流的末尾会被认为是一个错误,所以在这种情况下,这个函数会返回-1(也就是说,在一个关闭的套接字上或者在一个进程死后)。
QByteArray read(qint64 maxSize)
这是一个重载函数。
从设备中最多读取maxSize字节,并返回作为QByteArray读取的数据。
该函数没有报告错误的方法;返回None可能意味着当前没有数据可供读取,或者发生了错误。
QByteArray readAll()
从设备读取所有剩余数据,并以字节数组(byte array) 的形式返回。
该函数没有报告错误的方法;返回None可能意味着当前没有数据可供读取,或者发生了错误。
int readChannelCount()
返回设备处于打开状态时,可用的读取通道数;否则返回0。
这个函数是在Qt 5.7中引入的。
qint64 readLine(char *data, qint64 maxSize)
这个函数从设备中读取一行ASCII字符(最大为maxSize - 1字节),将字符存储在数据中,并返回读取的字节数。如果一行不能被读取,但是没有错误发生,这个函数返回0。如果发生错误,此函数将返回可读内容的长度,如果未读,则返回-1。
一个结束的“\0”字节总是附加到数据中,因此maxSize必须大于1。
读取数据,直到满足下列条件之一:
读取第一个’\n’字符。
maxSize -读取1个字节。
检测设备数据的结束。
例如,下面的代码从文件中读取一行字符:
file = QFile("box.txt")
if file.open(QFile.ReadOnly):
lineLength = file.readLine(buf, 1024);
if lineLength != -1:
// the line is available in buf
新行字符(’\n’)包含在缓冲区中。如果在读取maxSize - 1字节之前没有遇到换行,则不会将换行插入缓冲区。在windows中,换行符被替换为’\n’。
这个函数调用readLineData(),它是使用对getChar() 的重复调用实现的。通过在自己的子类中重新实现readLineData(),可以提供更有效的实现。
QByteArray readLine(qint64 maxSize = 0)
这是一个重载函数。
从设备中读取一行,但不超过maxSize字符,并以字节数组的形式返回结果。
该函数没有报告错误的方法;返回None可能意味着当前没有数据可供读取,或者发生了错误。
virtual bool reset()
随机访问设备移动到输入开始位置。成功返回True;否则返回false(例如,如果设备未打开)。
请注意,在QFile上使用QTextStream时,在QFile上调用reset() 不会得到预期的结果,因为QTextStream会缓冲该文件。使用QTextStream::seek() 函数。
void rollbackTransaction()
回滚已读事务。
将输入流还原到startTransaction() 调用的点。此函数通常用于在提交事务之前检测到未完成的读操作时回滚事务。
这个函数是在Qt 5.7中引入的。
virtual bool seek(qint64 pos)
对于随机访问设备,该函数将当前位置设置为pos,如果成功则返回true,如果发生错误则返回false。对于顺序设备,默认的行为是生成一个警告并返回false。
在子类化QIODevice时,必须在函数开始时调用QIODevice.seek(),以确保与QIODevice内置缓冲区的完整性。请参阅pos() 和isSequential()。
void setCurrentReadChannel(int channel)
将QIODevice的当前读通道设置为给定的通道。当前输入通道由函数read()、readAll()、readLine() 和getChar() 使用。它还确定哪个通道触发QIODevice发出readyRead() 。
这个函数是在Qt 5.7中引入的。
void setCurrentWriteChannel(int channel)
将QIODevice的当前写通道设置为给定的通道。当前输出通道由函数write()、putChar() 使用。它还确定哪个通道触发QIODevice发出bytesWritten()。
这个函数是在Qt 5.7中引入的。
void setTextModeEnabled(bool enabled)
如果enabled为真,此函数将设置设备上的文本标志;否则文本标记将被删除。这个特性对于在QIODevice上提供自定义行尾处理的类非常有用。
在调用这个函数之前,应该先打开IO设备。
virtual qint64 size()
对于打开的随机访问设备,此函数返回设备的大小。对于打开的顺序设备,将返回bytesAvailable()。
如果设备关闭,返回的大小将不反映设备的实际大小。
qint64 skip(qint64 maxSize)
从设备跳过最大字节数。返回实际跳过的字节数,或出错时返回-1。
这个函数不等待,只丢弃已经可以读取的数据。
如果设备以文本模式打开,行结束符将被转换为“\n”符号,并被视为与read() 和peek() 行为相同的单个字节。
该函数适用于所有设备,包括那些不能seek() 的连续设备。它被优化为在peek() 调用后跳过不需要的数据。
对于随机访问设备,可以使用skip()从当前位置向前查找。不允许使用负的maxSize值。
这个函数是在Qt 5.10中引入的。
void startTransaction()
在设备上启动一个新的读事务。
在读取操作序列中定义可恢复点。对于顺序设备,读取数据将在内部进行复制,以便在读取不完整的情况下进行恢复。对于随机访问设备,此函数保存当前位置。调用commitTransaction() 或rollbackTransaction() 来完成事务。
注意:不支持嵌套事务。
这个函数是在Qt 5.7中引入的。
void ungetChar(char c)
将字符c放回设备中,并递减当前位置,除非该位置为0。通常调用此函数来“撤消”getChar()操作,例如在编写回溯解析器时。
如果之前没有从设备中读取c,则行为是未定义的。
注意: 此函数在事务处理过程中不可用。
virtual bool waitForBytesWritten(int msecs)
对于缓冲设备,此函数将等待缓冲写入数据的有效负载被写入设备并发出byteswrite() 信号,或者等待msecs毫秒过去。如果msecs为-1,则此函数不会超时。对于未缓冲的设备,它立即返回。
如果将数据的有效负载写入设备,则返回true;否则返回false(例如,如果操作超时,或者发生了错误)。
这个函数可以在没有事件循环的情况下运行。它在编写非gui应用程序和在非gui线程中执行I/O操作时非常有用。
如果从连接到bytesWritten() 信号的槽中调用,则不会重新发出bytesWritten()。
重新实现此函数,为自定义设备提供阻塞API。默认实现不做任何事,并返回false。
警告:从主(GUI)线程调用此函数可能导致用户界面冻结。
virtual bool waitForReadyRead(int msecs)
阻塞直到有新的数据可供读取并发出readyRead() 信号,或者直到超过msecs毫秒。如果msecs为-1,则此函数不会超时。
如果新数据可用来读取,则返回true;否则返回false(如果操作超时或发生错误)。
这个函数可以在没有事件循环的情况下运行。它在编写非gui应用程序和在非gui线程中执行I/O操作时非常有用。
如果从连接到readyRead() 信号的槽中调用readyRead(),则不会重新发出readyRead()。
重新实现此函数,为自定义设备提供阻塞API。默认实现不做任何事,并返回false。
警告: 从主(GUI)线程调用此函数可能导致用户界面冻结。
qint64 write(const char *data, qint64 maxSize)
从数据写到设备的最大数据字节数。返回实际写入的字节数,如果发生错误则返回-1。
qint64 write(const char *data)
这是一个重载函数。
将以零结尾的 8位字符字符串中的数据写入设备。返回实际写入的字节数,如果发生错误则返回-1。这等价于
QIODevice.write(data, len(data))
这个函数是在Qt 4.5中引入的。
qint64 write(const QByteArray &byteArray)
这是一个重载函数。
将byteArray的内容写入设备。返回实际写入的字节数,如果发生错误则返回-1。
int writeChannelCount()
返回设备处于打开状态时可用的写通道数;否则返回0。
这个函数是在Qt 5.7中引入的。
Signals
void aboutToClose()
这个信号是在设备即将关闭时发出的。如果您有操作需要在设备关闭之前执行(例如,如果在一个单独的缓冲区中有数据需要写入设备),请连接此信号。
void bytesWritten(qint64 bytes)
每次将数据的有效负载写入设备的当前写入通道时,都会发出此信号。bytes参数被设置为在这个有效负载中写入的字节数。
bytesWritten() 不是递归发出的;如果在连接到bytesWritten() 信号的槽中重新输入事件循环或调用waitForBytesWritten() ,信号将不会被重新发出(尽管waitForBytesWritten() 可能仍然返回true)。
void channelBytesWritten(int channel, qint64 bytes)
每次将数据负载写入设备时,都会发出此信号。bytes参数被设置为在这个有效负载中写入的字节数,而channel是它们被写入的通道。与bytesWritten() 不同,它的发出与当前的写通道无关。
channelBytesWritten()可以递归地发出—甚至对于相同的通道。
这个函数是在Qt 5.7中引入的。
void channelReadyRead(int channel)
当设备上有新数据可读时,将发出此信号。通道参数被设置为数据到达的读通道的索引。与readyRead() 不同,它的发出与当前的读取通道无关。
可以递归地发出channelReadyRead()—甚至对于相同的通道也是如此。
这个函数是在Qt 5.7中引入的。
void readChannelFinished()
这个信号是在这个设备的输入(读取)流关闭时发出的。一旦检测到关闭,它就会发出,这意味着仍然可能有可用的数据可供read() 读取。
这个函数是在Qt 4.4中引入的。
void readyRead()
每次从设备的当前读取通道,读取新数据时,都会发出此信号。它只有在新数据可用时才会再次发出,例如当网络数据的新有效负载到达您的网络套接字时,或者当一个新的数据块附加到您的设备时。
readyRead() 不是递归发出的;如果在连接到readyRead() 信号的槽中重新输入事件循环或调用waitForReadyRead(),信号将不会被重新发出(尽管waitForReadyRead() 可能仍然返回true)。
对于实现从QIODevice派生的类的开发人员,请注意:当新数据到达时,应该总是发出readyRead()(不要发出它,因为缓冲区中还有数据需要读取)。在其他情况下不要发出readyRead()。
Protected Functions
virtual qint64 readData(char *data, qint64 maxSize)
读取设备中最多maxSize字节数据,并返回读取的字节数,如果发生错误则返回-1。
如果没有需要读取的字节,并且永远不可能有更多的可用字节(例如关闭套接字、关闭管道、完成子进程),则此函数返回-1。
这个函数由QIODevice调用。在创建QIODevice的子类时重新实现这个函数。
当重新实现这个函数时,在返回之前读取所有需要的数据是很重要的。为了使QDataStream能够对类进行操作,需要这样做。QDataStream假设读取了所有请求的信息,因此如果出现问题,不会重试读取。
可以使用maxSize为0调用此函数,可以使用maxSize执行读后操作。
virtual qint64 readLineData(char *data, qint64 maxSize)
略
void setErrorString(const QString &str)
略
void setOpenMode(QIODevice::OpenMode openMode)
略
virtual qint64 writeData(const char *data, qint64 maxSize)
略