本文用于介紹 QIODevice 類,該類是 QSerialPort 的父類。
系統(tǒng)環(huán)境:Win10 64位
轉(zhuǎn)載請注明出處:http://m.itdecent.cn/u/5e6f798c903a
4.QIODevice 類
官方文檔
Header: #include <QSerialPort>
qmake: QT += core
Inherits: QObject
Inherited By: QAbstractSocket, QBluetoothSocket, QBuffer, QFileDevice, QLocalSocket, QNetworkReply, QProcess, and QSerialPort
為了便于理解,這里給出本節(jié)內(nèi)容的思維導圖:( 本節(jié)后面的內(nèi)容也遵循此結(jié)構(gòu) )

4.1 簡介
QIODevice 類是 Qt 中所有 I/O 設(shè)備的基礎(chǔ)接口類。
QIODevice 為支持數(shù)據(jù)塊讀寫的設(shè)備 (如:QFile, QBuffer 和 QTcpSocket) 提供了通用實現(xiàn)和抽象接口。
QIODevice 屬于抽象類,不能被實例化,但通常會使用由 QIODevice 定義的接口來提供設(shè)備共有的 I/O 特性。例如,Qt 的 XML 類運行在 QIODevice 指針上,以允許 XML 類可與各種設(shè)備( 如文件和緩存 )一同被使用。
在訪問設(shè)備之前,必須調(diào)用 open() 函數(shù),以設(shè)置正確的 OpenMode (如 ReadOnly 或 ReadWrite)。然后,可以調(diào)用 write() 或 putChar() 進行寫入,或調(diào)用 read()、readLine()、readAll() 進行讀取。完成操作后,調(diào)用 close() 關(guān)閉設(shè)備。
QIODevice 可識別兩種設(shè)備類型(可調(diào)用 isSequential() 來確定設(shè)備的類型):
- 隨機訪問設(shè)備( random-access devices ),支持使用 seek() 來查找任意位置。通過調(diào)用 pos(),可獲得在文件中的當前位置。QFile 和 QBuffer 便屬于這類設(shè)備。
- 順序設(shè)備( sequential devices ),不支持查找任意位置。數(shù)據(jù)必須被一次性讀取。函數(shù) pos() and size() 不適用于順序設(shè)備。 QTcpSocket and QProcess 便屬于這類設(shè)備。
當有可供讀取的新數(shù)據(jù)時,QIODevice 會發(fā)出 readyRead() 信號(比如,網(wǎng)絡上有新數(shù)據(jù)抵達時,或是有新數(shù)據(jù)被追加到正在讀取的文件時)。bytesAvailable() 用于確定當前可供讀取的字節(jié)數(shù)。為異步設(shè)備(如 QTcpSocket )編寫程序時,通常會同時使用 bytesAvailable() 和 readyRead() ,因為異步設(shè)備的數(shù)據(jù)片段可能會在任意時間點到達。每當數(shù)據(jù)載荷被寫入設(shè)備時,QIODevice 便會發(fā)射 bytesWritten() 信號。bytesToWrite() 用于確定當前等待寫入的數(shù)據(jù)總量。
QIODevice 的某些子類屬于異步子類,比如 QTcpSocket 和 QProcess 。這些子類的 I/O 函數(shù)(如 write() 、read() )總是立即返回,等控制權(quán)返回事件循環(huán)后,才會和設(shè)備本身進行通訊。QIODevice 還提供了相應的函數(shù),以便強制 I/O 操作被立即執(zhí)行,同時會阻塞調(diào)用線程,而不會進入事件循環(huán)。以下函數(shù)便具有這樣的特性,但不要在事件循環(huán)中使用它們,或是在另外一個單獨的線程中使用。
- waitForReadyRead() - 該函數(shù)會在調(diào)用線程中掛起操作,直到有可供讀取的新數(shù)據(jù)為止。
- waitForBytesWritten() - 該函數(shù)在調(diào)用線程中掛起操作,直到一個數(shù)據(jù)載荷被寫入到設(shè)備為止。
- waitFor....() - 在 QIODevice 的子類中,針對設(shè)備特有的操作實現(xiàn)的阻塞函數(shù)。例如,例如, QProcess 有一個叫做 waitForStarted() 的函數(shù),可在調(diào)用線程中掛起操作直到進程啟動。
在主線程或 GUI 線程中調(diào)用以上函數(shù),可能會導致用戶界面凍結(jié)。例如:
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 設(shè)備提供相同的接口。QIODevice 的子類僅需要實現(xiàn)受保護的 readData() 和 writeData() 函數(shù)。QIODevice 使用這兩個函數(shù)來實現(xiàn)相關(guān)函數(shù)(如, getChar()、readLine() 和 write()),使操作更加便捷。QIODevice 還會為我們處理訪問控制,因此如果調(diào)用了 writeDate(),則可以安全地假定設(shè)備以寫模式打開。
像 QFile 和 QTcpSocket 這樣的子類,會使用內(nèi)存緩沖區(qū)來實現(xiàn)中間數(shù)據(jù)的存儲。這種方式減少了訪問設(shè)備( 這里的設(shè)備指 file、socket 等 )的次數(shù),但這種方式通常非常慢。使用 getChar() 和 putChar() 這樣的函數(shù)訪問緩沖區(qū),會更加快捷。因為這些函數(shù)在內(nèi)存緩沖區(qū)中運行,而非直接運行在設(shè)備中。但是,某些 I/O 操作對緩沖區(qū)不起作用,例如:如果多個用戶都打開了相同的設(shè)備并逐一讀取每個字符,那么當用戶打算讀取各自所需的數(shù)據(jù)塊時,它們最終可能會讀取到相同的數(shù)據(jù)。出于此原因,QIODevice 允許允許向 open() 函數(shù)傳遞 Unbuffered 標志來忽略任何緩沖。在創(chuàng)建 QIODevice 的子類時,當設(shè)備在 Unbuffered 模式下被打開后,記得忽略任何緩沖區(qū)。
通常情況下,來自異步設(shè)備的數(shù)據(jù)流是片段華的,數(shù)據(jù)塊可能會在任意時間點到達。要處理讀取到的不完整的數(shù)據(jù)結(jié)構(gòu),可使用由 QIODevice 實現(xiàn)的事務處理機制。詳細信息,請參閱 startTransaction() 及相關(guān)函數(shù)。
某些順序設(shè)備支持通過多通道通訊。通道代表獨立的數(shù)據(jù)流,擁有相互獨立的發(fā)送順序。一旦相應設(shè)備被打開,便可通過調(diào)用 readChannelCount() 和 writeChannelCount() 函數(shù)來確定通道的數(shù)量。需要切換通道時,請分別調(diào)用 setCurrentReadChannel() 和 setCurrentWriteChannel()。QIODevice 還提供了額外的信號,用于處理基于每個通道的異步通訊。
4.2 創(chuàng)建對象
- QIODevice::QIODevice()
構(gòu)建一個 QIODevice 對象。
- QIODevice::QIODevice(QObject *parent)
使用給定的父對象構(gòu)建一個 QIODevice 對象。
- QIODevice::~QIODevice()
[virtual]
該析構(gòu)函數(shù)是虛擬的,QIODevice 屬于抽象基類。該析構(gòu)函數(shù)不會調(diào)用 close(),但是其子類的析構(gòu)函數(shù)可能會調(diào)用。如果有疑慮,請在銷毀 QIODevice 前調(diào)用 close()。
4.3 打開模式
enum QIODevice::OpenModeFlag 枚舉配合 open() 函數(shù)使用,用于描述設(shè)備的打開方式??捎猛ㄟ^ openMode() 函數(shù)可查看設(shè)備的打開模式。
| Constant | Value | Description |
|---|---|---|
QIODevice::NotOpen |
0x0000 |
設(shè)備沒有被打開 |
QIODevice::ReadOnly |
0x0001 |
以讀模式被打開 |
QIODevice::WriteOnly |
0x0002 |
以寫模式被打開,該模式意味著截斷 |
QIODevice::ReadWrite |
ReadOnly WriteOnly
|
以讀/寫模式打開 |
QIODevice::Append |
0x0004 |
以追加模式打開設(shè)備,所有數(shù)據(jù)會被追加到文件的末尾。 |
QIODevice::Truncate |
0x0008 |
如果可能的話,設(shè)備會在被打開之前截斷。 調(diào)用 open() 函數(shù)之前的內(nèi)容,都會丟失。 |
QIODevice::Text |
0x0010 |
在讀取時,行終止符被轉(zhuǎn)換為 \n 。在寫入時,行終止符被轉(zhuǎn)換為平臺相關(guān)的本地編碼。比如 Win32 對應 \r\n 。 |
QIODevice::Unbuffered |
0x0020 |
設(shè)備中的任何緩沖區(qū)都將被忽略。 |
因為子類表示的設(shè)備類型會隱含某些限制條件。所以某些標志 ( 如 Unbuffered 和 Truncate ) 配合某些子類使用時,可能沒有實際意義。有些情況下,實現(xiàn)方式也會導致一些限制,另外底層平臺也會施加一些限制。例如,QTcpSocket 不支持 Unbuffered 模式;另外在 Windows 中由于本地 API 的限制,使得 QFile 不支持 Unbuffered模式。
flags QIODevice::OpenMode 是由 QFlags<PinoutSignal> 定義的類型。該類型可使用 OR 運算對 OpenMode 中的值進行組合。
void QIODevice::setOpenMode(OpenMode openMode)
[protected]
將設(shè)備的打開方式設(shè)置為 openMode 。
如果需要在設(shè)備被打開后改變其打開方式,可調(diào)用該函數(shù)進行設(shè)置。OpenMode QIODevice::openMode() const
返回已打開的設(shè)備的打開方式,比如:ReadOnly 或 WriteOnly。bool QIODevice::isTextModeEnabled() const
如果打開模式中開啟了 Text 標記,便會返回true;否則返回false。void QIODevice::setTextModeEnabled(bool enabled)
假如 enabled 的值為true,則會在設(shè)備的打開模式中添加 Text 標記;如果 enable 的值為false,則會從打開模式中移除 Text 標記。該特性對于在 QIODevice 上提供具備自定義行尾處理功能的類非常有用。
調(diào)用此函數(shù)前,應確保 IO 設(shè)備已被打開。
4.4 打開設(shè)備
- bool QIODevice::open(OpenMode mode)
[virtual]
打開設(shè)備,并將設(shè)備的打開方式設(shè)置為 mode 。如果設(shè)置成功,返回true;否則返回false。該函數(shù)應該在任何 open() 函數(shù)的重實現(xiàn)中被調(diào)用,或任何其它用于打開的設(shè)備的函數(shù)中被調(diào)用。
- bool QIODevice::isOpen() const
如果設(shè)備已被打開,返回true,否則返回false。
如果某設(shè)備可被讀取和(或)寫入,則該設(shè)備已被打開。默認情況下,如果openMode()返回NotOpen,則該函數(shù)返回false。
4.5 關(guān)閉設(shè)備
公共函數(shù)
- void QIODevice::close()
[virtual]
調(diào)用該函數(shù)后,首先會發(fā)射aboutToClose()信號,然后關(guān)閉設(shè)備并將 OpenMode 設(shè)置為 NotOpen。錯誤字符串也會被重置。
信號
- void QIODevice::aboutToClose()
[signal]
當設(shè)備即將關(guān)閉時,便會發(fā)送此信號。如果在關(guān)閉設(shè)備之前需要執(zhí)行某些操作,可將其連接到此信號。比如,在一個獨立的緩沖區(qū)中,如果存在需要被寫入到設(shè)備中的數(shù)據(jù),便可利用該信號。以確保在設(shè)備關(guān)閉前,將這部分數(shù)據(jù)被寫入到設(shè)備中。
4.6 讀取數(shù)據(jù)
讀取字符串
-
qint64 QIODevice::read(char *data, qint64 maxSize)
從設(shè)備中最多讀取 maxSize 字節(jié)的數(shù)據(jù)到 data 中,并返回讀取到的字節(jié)數(shù)。如果發(fā)生錯誤(比如嘗試從 WriteOnly 模式的設(shè)備中讀取數(shù)據(jù)),會返回-1。
當沒有更多的數(shù)據(jù)可供讀取時,返回0。
在數(shù)據(jù)流終止之后進行讀取,同樣會報錯,即返回-1。比如讀取已關(guān)閉的套接字,或讀取已死掉的進程。
QByteArray QIODevice::read(qint64 maxSize)
這是一個重載函數(shù)。
該函數(shù)會從設(shè)備讀取最多 maxSize 字節(jié)的數(shù)據(jù),并以 QByteArray 類型返回。
該函數(shù)不能報告錯誤,如果返回空 QByteArray 數(shù)組,可能意味著當前沒有可供讀取的數(shù)據(jù),也可能意味著發(fā)生了錯誤。qint64 QIODevice::readData(char data, qint64maxSize*)
[pure virtual protected]
最多從設(shè)備中讀取 maxSize 字節(jié)的數(shù)據(jù)到 data 中,并返回讀取到的字節(jié)數(shù)。如果發(fā)生錯誤,則返回-1。
如果沒有讀取到任何字節(jié),并且以后也不會有更多可用字節(jié)時,該函數(shù)會返回-1(比如套接字已關(guān)閉、管道已關(guān)閉、子進程已結(jié)束)。
該函數(shù)由 QIODevice 調(diào)用。創(chuàng)建 QIODevice 的子類時,需要重實現(xiàn)該函數(shù)。
重實現(xiàn)該函數(shù)時,最重要的是在函數(shù)返回前讀取所有需要的數(shù)據(jù)。為了讓 QDataStream 能夠在類上運行,這是必需的。QDataStream 會假定所有請求的信息都已被讀取,因此如果出現(xiàn)問題,也不會重新嘗試讀取數(shù)據(jù)。
該函數(shù)可被調(diào)用(需要將參數(shù) maxSize 設(shè)置為 0),用于執(zhí)行 post-reading 操作。-
qint64 QIODevice::readLine(char *data, qint64 maxSize)
該函數(shù)會從設(shè)備中讀取一行 ASCII 字符(最多會讀取 maxSize -1 個字節(jié)),讀取到的字符被儲存在 data 中,返回值表示讀取到的字節(jié)數(shù)。如果某行無法被讀取,但也沒有發(fā)生錯誤,該函數(shù)會返回0。如果發(fā)生錯誤,該函數(shù)會返回可供讀取長度,如果此時沒有可供讀取的數(shù)據(jù),則返回-1。
Tips:該函數(shù)始終會在 data 的末尾添加終止符\0,因此 maxSize 必須大于 1。
滿足下列條件之一,便會停止讀取數(shù)據(jù):- 讀取到
\n字符; - 已讀取到 maxSize - 1 個字節(jié);
- 檢測到設(shè)備數(shù)據(jù)的結(jié)束。
示例,以下代碼會從文件中讀取一行字符:
QFile file("box.txt"); if (file.open(QFile::ReadOnly)) { char buf[1024]; qint64 lineLength = file.readLine(buf, sizeof(buf)); if (lineLength != -1) { // the line is available in buf } }換行符
\n同樣會包含在緩沖器中,如果在前 maxSize - 1 個被讀取到的字節(jié)中未包含換行符,則不會在緩沖器中插入換行符。在 Windows 中換行符會被替換為\n。
該函數(shù)會調(diào)用readLineData(),readLineData()通過重復調(diào)用getChar()實現(xiàn)。在自己的子類中可以重實現(xiàn)readLineData()函數(shù),以為readLine()提供更高效的實現(xiàn)。 - 讀取到
QByteArray QIODevice::readLine(qint64 maxSize = 0)
此函數(shù)為重載函數(shù)。
該函數(shù)會從設(shè)備讀取一行數(shù)據(jù),但是數(shù)據(jù)的長度不超過 maxSize 個字符,返回值是 QByteArray 類型。
該函數(shù)不能報告錯誤,如果返回空 QByteArray 數(shù)組,可能意味著當前沒有可供讀取的數(shù)據(jù),也可能意味著發(fā)生了錯誤。qint64 QIODevice::readLineData(char data, qint64maxSize*)
[virtual protected]
最多從設(shè)備中讀取 maxSize 字節(jié)的數(shù)據(jù)到 data 中,并返回讀取到的字節(jié)數(shù)。
該函數(shù)由readLine()調(diào)用,并使用getChar()提供它的基本實現(xiàn)。帶有緩沖區(qū)的設(shè)備可以通過重實現(xiàn)該函數(shù)來提高readLine()的性能。
readLine()會向 data 追加\0字符,但是readLineData()不需要這樣做。
如果需要重實現(xiàn)該函數(shù),一定要注意是否返回了正確的值:該函數(shù)應返回在一行中讀取到的字節(jié)數(shù)(包含末尾處的換行符);如果此處沒有可供讀取的行,則返回0。如果發(fā)生錯誤,當且僅當沒有字節(jié)被讀取時,應該返回-1。在 EOF(文件結(jié)束符)后進行讀取被認為錯誤的。QByteArray QIODevice::readAll()
從設(shè)備中讀取所有剩余數(shù)據(jù),并以 QByteArray 類型返回。
該函數(shù)不能報告錯誤,如果返回空 QByteArray 數(shù)組,可能意味著當前沒有可供讀取的數(shù)據(jù),也可能意味著發(fā)生了錯誤。
讀取字符
bool QIODevice::getChar(char *c)
從設(shè)備中讀取一個字符,并將其儲存在 c 中。如果 c 是 0,該字符會被丟棄。
成功讀取,返回true;否則返回false。-
void QIODevice::ungetChar(char c)
將字符 c 放回到設(shè)備中。字符 c 會被放置在緩沖區(qū)的首位,其它內(nèi)容的位置依次后移一位,示例如下:port = QSerialPort('COM1') port.open(QIODevice.ReadWrite) print(port.readBufferSize()) port.setReadBufferSize(2) print(port.readBufferSize()) port.ungetChar(b'1') port.ungetChar(b'2') port.ungetChar(b'3') print(port.readAll()) port.close()輸出:
0 2 b'321'該函數(shù)常被用于撤銷 getChar() 操作。比如編寫回溯分析程序時,便可使用該函數(shù)。
如果之前并沒有從設(shè)備讀取 c ,則無法確定具體行為。
Note: This function is not available while a transaction is in progress.
信號
- void QIODevice::readyRead()
[signal]
在設(shè)備當前的讀取通道中,每當有可供讀取的新數(shù)據(jù)時,該信號便會被發(fā)送一次。一旦有新數(shù)據(jù)可用,該信號便會被再次發(fā)送,比如當新的網(wǎng)絡數(shù)據(jù)載荷已經(jīng)到達網(wǎng)絡套接字時,便會發(fā)送該信號。另外當新的數(shù)據(jù)塊被追加到設(shè)備時,也會發(fā)送此信號。
readyRead()不會被遞歸發(fā)射,如果在連接到readyRead()的曹函數(shù)中重新進入事件循環(huán),或在曹函數(shù)中調(diào)用waitForReadyRead(),那么readyRead()信號將不會重復發(fā)送( 雖然waitForReadyRead()仍然可能返回true)。
開發(fā)人員由 QIODevice 實現(xiàn)派生類時,應注意:每當有新數(shù)據(jù)到達時,總應該發(fā)送readyRead()信號(不要僅因為在緩沖區(qū)中任然有數(shù)據(jù)被讀取,就發(fā)送該信號)。在其它情況下情不要發(fā)送readyRead()信號。
其它函數(shù)
bool QIODevice::waitForReadyRead(int msecs)
[virtual]
該函數(shù)會阻塞調(diào)用,直到有可供讀取的新數(shù)據(jù)為止(同時會發(fā)送 readyRead() 信號)。該函數(shù)會在 msecs 毫秒后發(fā)生超時。如果 msecs 被設(shè)置為 -1,則不會發(fā)生超時。
如果存在可供讀取的新數(shù)據(jù),則返回true;如果發(fā)生錯誤或操作超時,則返回false。
執(zhí)行該函數(shù)時,無需事件循環(huán)。在編寫非 GUI 程序,以及在非 GUI 線程中執(zhí)行 I/O 操作時,該函數(shù)會非常實用。
如果在連接到readRead()信號的曹函數(shù)中調(diào)用waitForReadyRead(),那么readyRead()信號不會被重復發(fā)送。
為自定義設(shè)備重實現(xiàn)該函數(shù)以提供非阻塞 API 時,默認的實現(xiàn)方式是什么也不做,并且返回false。
<u>Warning:</u>從主(GUI)線程調(diào)用該函數(shù),可能會導致用戶界面凍結(jié)。-
qint64 QIODevice::bytesAvailable() const
[virtual]
返回可供讀取的字節(jié)數(shù)。該函數(shù)通常配合順序設(shè)備使用,以便在讀取之前確定被分配到緩沖區(qū)中的字符數(shù)。
重實現(xiàn)此函數(shù)的子類必須調(diào)用基本實現(xiàn),以包含 QIODevice 的緩沖區(qū)的尺寸。例如:qint64 CustomDevice::bytesAvailable() const { return buffer.size() + QIODevice::bytesAvailable(); }
bool QIODevice::isReadable() const
如果可以從設(shè)備讀取數(shù)據(jù)返回true,否則返回false。使用byteAvailable()可以確定可被讀取的字節(jié)數(shù)。
該函數(shù)可以很方便的查詢設(shè)備的打開模式中是否包含ReadOnly標識。-
bool QIODevice::canReadLine() const
[virtual]
如果可以從設(shè)備讀取一行完整的數(shù)據(jù),會返回true。否則返回false。
注意:無緩沖區(qū)的設(shè)備,由于無法確定可供讀取的內(nèi)容,因此總是返回false。
該函數(shù)經(jīng)常同 readyRead() 信號一起被調(diào)用。
重新實現(xiàn)此函數(shù)的子類必須調(diào)用基本實現(xiàn),以包含 QIODevice 的緩沖區(qū)的內(nèi)容。例如:bool CustomDevice::canReadLine() const { return buffer.contains('\n') || QIODevice::canReadLine(); }
4.7 寫入數(shù)據(jù)
寫入字符串
-
qint64 QIODevice::write(const char *data, qint64 maxSize)
從 data 中寫入最多 maxSize 字節(jié)的數(shù)據(jù)到設(shè)備中。
返回實際被寫入的字節(jié)數(shù);如果發(fā)生錯誤,則返回 -1。
-
qint64 QIODevice::write(const char *data)
此函數(shù)是重載函數(shù)。
將由 8-bit 字符組成的字符串(以 0 結(jié)尾),寫入到設(shè)備。
返回實際被寫入的字節(jié)數(shù);如果發(fā)生錯誤,則返回 -1。
該函數(shù)相當于:... QIODevice::write(data, qstrlen(data)); ...該函數(shù)在 Qt 4.5 被引入。
qint64 QIODevice::write(const QByteArray &byteArray)
此函數(shù)是重載函數(shù)。
將 byteArray 中的內(nèi)容寫入到設(shè)備。
返回實際被寫入的字節(jié)數(shù);如果發(fā)生錯誤,則返回 -1。qint64 QIODevice::writeData(const char *data, qint64 maxSize)
[pure virtual protected]
從 data 中寫入最多 maxSize 字節(jié)的數(shù)據(jù)到設(shè)備中。
返回被寫入的字節(jié)數(shù);如果發(fā)生錯誤,則返回 -1。
該函數(shù)由 QIODevice 調(diào)用。創(chuàng)建 QIODevice 的子類時,需要重實現(xiàn)該函數(shù)。
重實現(xiàn)該函數(shù)時,最中要的是在函數(shù)返回前寫入所有可用的數(shù)據(jù)。為了讓 QDataStream 能夠在類上運行,這是必需的。QDataStream 會假定所有的信息都已被寫入,因此如果出現(xiàn)問題,也不會嘗試重新寫入數(shù)據(jù)。
寫入字符
- bool QIODevice::putChar(char c)
將字符 c 寫入到設(shè)備。返回true表示寫入成功;否則返回false。
信號
- void QIODevice::bytesWritten(qint64 bytes)
[signal]
每當數(shù)據(jù)的有效載荷被寫入設(shè)備的當前寫入通道時,就會發(fā)出此信號。bytes 參數(shù)被設(shè)置為在有效載荷中被寫入的字節(jié)數(shù)。
bytesWritten() 不會遞歸發(fā)射; 如果重新進入事件循環(huán),或在連接到 bytesWritten() 信號的插槽內(nèi)調(diào)用 waitForBytesWritten(),信號將不會被重新發(fā)送(雖然 waitForBytesWritten() 仍然可以返回true)。
其它函數(shù)
- bool QIODevice::waitForBytesWritten(int msecs)
[virtual]
對于擁有緩沖區(qū)的設(shè)備,該函數(shù)會一直等待,直到緩沖區(qū)寫入數(shù)據(jù)的有效載荷被寫入設(shè)備(同時會發(fā)送 bytesWritten() 信號),或是等待 msecs 毫秒后發(fā)生超時。如果 msecs 被設(shè)置為 -1,則不會發(fā)生超時。
對于沒有緩沖區(qū)的設(shè)備,該函數(shù)會立即返回。
如果數(shù)據(jù)的有效載荷已經(jīng)被寫入設(shè)備,則返回true;如果發(fā)生錯誤或操作超時,則返回false。
執(zhí)行該函數(shù)時,無需事件循環(huán)。在編寫非 GUI 程序,以及在非 GUI 線程中執(zhí)行 I/O 操作時,該函數(shù)會非常實用。
如果在連接到bytesWritten()信號的曹函數(shù)中調(diào)用waitForBytesWritten(),那么bytesWritten()信號不會被重復發(fā)送。
為自定義設(shè)備重實現(xiàn)該函數(shù)以提供非阻塞 API 時,默認的實現(xiàn)方式是什么也不做,并且返回false。
<u>Warning:</u>從主(GUI)線程調(diào)用該函數(shù),可能會導致用戶界面凍結(jié)。
-
qint64 QIODevice::bytesToWrite() const
[virtual]
對于擁有緩沖區(qū)的設(shè)備,該函數(shù)會返回等待寫入的字符數(shù)。
對于沒有緩沖區(qū)的設(shè)備,該函數(shù)返回 0。
重實現(xiàn)此函數(shù)的子類必須調(diào)用基本實現(xiàn),以包含 QIODevice 的緩沖區(qū)的尺寸。 - bool QIODevice::isWritable() const
如果可以向設(shè)備寫入數(shù)據(jù),則返回true;否則返回false。
該函數(shù)可以很方便的查詢設(shè)備的打開模式中是否包含WriteOnly標識。
4.8 查看數(shù)據(jù)
-
qint64 QIODevice::peek(char *data, qint64 maxSize)
從設(shè)備中最多讀取 maxSize 字節(jié)的數(shù)據(jù)到 data 中,并返回讀取到的字節(jié)數(shù)。該函數(shù)不會有任何副作用,也就是所在peek()之后調(diào)用read(),將會獲得相同的數(shù)據(jù)。
如果發(fā)生錯誤(比如嘗試從 WriteOnly 模式的設(shè)備中查看數(shù)據(jù)),會返回-1。
當沒有更多的數(shù)據(jù)可供讀取時,返回0。示例:
{ char buf[2]; if (file->peek(buf, sizeof(buf)) == sizeof(buf)) return (buf[0] == 'M' && buf[1] == 'Z'); return false; }該函數(shù)在 Qt 4.1 被引入。
-
QByteArray QIODevice::peek(qint64 maxSize)
這是一個重載函數(shù)。
該函數(shù)會從設(shè)備查看最多 maxSize 字節(jié)的數(shù)據(jù),并以 QByteArray 類型返回。
示例:bool isExeFile(QFile *file) { return file->peek(2) == "MZ"; }該函數(shù)不能報告錯誤,如果返回空 QByteArray 數(shù)組,可能意味著當前沒有可供查看的數(shù)據(jù),也可能意味著發(fā)生了錯誤。
該函數(shù)在 Qt 4.1 被引入。
4.9 跳過數(shù)據(jù)
-
qint64 QIODevice::skip(qint64 maxSize)
從設(shè)備中跳過最多 maxSize 字節(jié)。該函數(shù)會返回實際跳過的字節(jié)數(shù);發(fā)生錯誤時,返回-1。該函數(shù)不會等待,只會直接丟棄已經(jīng)存在的可供讀取的數(shù)據(jù)。如果設(shè)備以 text 模式被打開,則行結(jié)束符會被翻譯為\n,并在計數(shù)時被視作一個字節(jié)(這點同read()和peek()的行為相同)。此函數(shù)適用與所有設(shè)備,包含不能使用seek()的順序設(shè)備。在peek()之后調(diào)用該函數(shù),可以很方便的跳過不想要的數(shù)據(jù)。對于隨機訪問設(shè)備,skip()被用于從當前位置向前查找。maxSize 不可使用負值。
該函數(shù)在 Qt 5.11 被引入。
4.10 讀寫位置
- bool QIODevice::seek(qint64 pos)
[virtual]
對于隨機訪問設(shè)備,該函數(shù)會將當前位置設(shè)置為 pos 。如果設(shè)置成功,則返回true;如果發(fā)生錯誤,則返回false。對于順序設(shè)備,默認行為是產(chǎn)生警告并返回false。
子類化 QIODevice 時,必須在函數(shù)的開頭調(diào)用QIODevice::seek(),以確保 QIODevice 內(nèi)建緩沖區(qū)的完整性。 -
qint64 QIODevice::pos() const
[virtual]
對于隨機訪問設(shè)備,該函數(shù)會返回寫入或讀取數(shù)據(jù)的位置。對于順序設(shè)備或已關(guān)閉的設(shè)備而言,它們并沒有“當前位置”的概念,因此會返回0。
設(shè)備當前的讀/寫位置由內(nèi)部的 QIODevice 維護,因此該函數(shù)并非必須被重實現(xiàn)。在繼承QIODevice時,需要使用QIODevice::seek()來通知 QIODevice 設(shè)備位置的變化。 - bool QIODevice::reset()
[virtual]
查找隨機訪問設(shè)備輸入的起始位置。如果成功,返回true;否則返回false(比如并未打開設(shè)備)
注意,在 QFile 中使用 QTextStream 時,由于 QTextStream 會緩存文件,所以在 QFile 上調(diào)用reset()將不會產(chǎn)生預期的結(jié)果,此時需要改用 QTextStream::seek() 函數(shù)。 - bool QIODevice::atEnd() const
[virtual]
如果當前讀寫位置處于設(shè)備的末端(即設(shè)備中沒有更多可供讀取的數(shù)據(jù)),將返回true;否則返回false。
對于某些設(shè)備,即使仍有可被讀取的數(shù)據(jù),但是atEnd()也會返回true。這種特殊的情況僅適用于,間接響應read()調(diào)用來生成數(shù)據(jù)的設(shè)備(比如,在 Unix 和 MacOS 中的/devor/proc文件,或是所有平臺上的 console input 和stdin)。
4.11 信道
公共函數(shù)
- int QIODevice::currentReadChannel() const
返回當前讀信道的索引值。
該函數(shù)在 Qt 5.7 被引入。 - int QIODevice::readChannelCount() const
如果設(shè)備處于打開狀態(tài),則返回可用于讀取的信道的數(shù)量;否則返回 0。
該函數(shù)在 Qt 5.7 被引入。 - void QIODevice::setCurrentReadChannel(int channel)
將 QIODevice 當前的讀取通道設(shè)置為給定通道 channel 。當前輸入通道會被 read(), readAll(), readLine(), getChar() 函數(shù)使用。還用于確定觸發(fā) QIODevice 發(fā)送readyRead()信號的通道。
該函數(shù)在 Qt 5.7 被引入。
- int QIODevice::currentWriteChannel() const
返回當前寫信道的索引值。
該函數(shù)在 Qt 5.7 被引入。 - int QIODevice::writeChannelCount() const
如果設(shè)備處于打開狀態(tài),則返回可用于寫入的信道的數(shù)量;否則返回 0。
該函數(shù)在 Qt 5.7 被引入。 - void QIODevice::setCurrentWriteChannel(int channel)
將 QIODevice 當前的寫入通道設(shè)置為給定通道 channel 。當前輸出通道會被 write(), putChar() 函數(shù)使用。還用于確定了觸發(fā) QIODevice 發(fā)送 bytesWritten() 信號的通道。
該函數(shù)在 Qt 5.7 被引入。
信號
- void QIODevice::channelReadyRead(int channel)
[signal]
當有來自設(shè)備的可供讀取的新數(shù)據(jù)時,便會發(fā)送此信號。 會將收到新數(shù)據(jù)的讀信道的索引值設(shè)置為 channel 的值。與readyRead()不同,無論當前處于哪一個讀信道,該信號總會被發(fā)送。
channelReadyRead()可以被遞歸發(fā)送,即使處于同一的信道中。
該函數(shù)在 Qt 5.7 被引入。 - void QIODevice::readChannelFinished()
[signal]
當設(shè)備中的輸入(讀?。┝鞅魂P(guān)閉時,就會發(fā)送此信號。一旦檢測到流被關(guān)閉,便會發(fā)送此信號,這意味著可能仍然存在可供讀取read()的數(shù)據(jù)。
該函數(shù)在 Qt 4.4 被引入。 - void QIODevice::channelBytesWritten(int channel, qint64 bytes)
[signal]
每當數(shù)據(jù)有效載荷被寫入設(shè)備時,便會發(fā)送該信號。有效載荷中被寫入的字節(jié)數(shù)會被設(shè)置為 bytes 的值;用于寫入數(shù)的信道的索引值會被設(shè)置為 channel 的值。與bytesWritten()不同,無論當前處理哪一個寫信道,該信號總會被發(fā)送。
channelBytesWritten()可以被遞歸發(fā)送,即使處于同一信道中。
該函數(shù)在 Qt 5.7 被引入。
4.12 設(shè)備類型查詢
- bool QIODevice::isSequential() const
[virtual]
如果該設(shè)備是順序設(shè)備,則返回true;否則返回false。
與隨機訪問設(shè)備相反,順序設(shè)備不具備如下概念:開始、結(jié)束、大小、當前位置,也不支持查找位置(seek)。當設(shè)備報告有可用數(shù)據(jù)時,我們也只能從設(shè)備讀取數(shù)據(jù)。最常見的順序設(shè)備時網(wǎng)絡套接字。在 Unix 上,特殊文件也是順序設(shè)備(如 /dev/zero 和 fifo pipes )。
另一方面,Regular files 支持隨機訪問。它們具備尺寸大小和當前位置的概念,同時還支持在數(shù)據(jù)流中向后和向前查找位置(seek)。Regular files 是非順序設(shè)備。
4.13 設(shè)備大小查詢
-
qint64 QIODevice::size() const
[virtual]
對于已打開的隨機訪問設(shè)備,該函數(shù)會返回設(shè)備的 size。
對于已打開的順序設(shè)備,該函數(shù)會返回 bytesAvailable()。
如果設(shè)備已被關(guān)閉,返回值并不能反映出設(shè)備的實際 size。
4.14 事務處理
- void QIODevice::startTransaction()
在設(shè)備上啟動新的讀取事務。
在讀操作序列的內(nèi)部定義一個可還原點。對于順序設(shè)備,讀取的數(shù)據(jù)將在內(nèi)部被復制,以便在沒有完全讀取的情況下進行恢復。對于隨機訪問設(shè)備,該函數(shù)會保存當前位置。調(diào)用 commitTransaction() 或 rollbackTransaction() 可結(jié)束事務。
注意:不支持嵌套事務。
該函數(shù)在 Qt 5.7 被引入。 - bool QIODevice::isTransactionStarted() const
如果設(shè)備的進程中存在已啟動的事務,則返回true,否則返回false。
該函數(shù)在 Qt 5.7 被引入。 - void QIODevice::rollbackTransaction()
回滾讀取事務。
將輸入流恢復到 startTransaction() 創(chuàng)建的還原點處。在提交事務之前,如果檢測到被讀取的數(shù)據(jù)并不完整,通常會使用該函數(shù)回滾事務。
該函數(shù)在 Qt 5.7 被引入。 - void QIODevice::commitTransaction()
完成讀取事務。
對于序列設(shè)備,在事務期間被記錄在內(nèi)部緩沖區(qū)中的所有數(shù)據(jù)都將被丟棄。
該函數(shù)在 Qt 5.7 被引入。