QFile
0、說明
QFile是讀寫文件的類,這里的文件包括文本文件、二進制文件、資源文件。
通常情況下,文件讀寫使用QFile、QTextStream、QDataStream就夠了。
file name在構造QFile時傳入,或者通過setFileName()自己設置。不管什么OS,QFile中的分隔符都是 '/'。其它分隔符均不支持。
通過exists()檢查文件是否存在,用remove()移除文件(更多文件系統相關的操作可見QFileInfo and QDir.)
通過open()打開文件,close()關閉文件,flush()刷新文件。
文件中的數據通常用QDataStream or QTextStream讀寫,當然也可以直接調用從QIODevice繼承下來的read()、readLine()、readAll()、write()進行讀寫。QFile也繼承了getChar()、putChar()、ungetChar(),這些方法一次操作單個字符。
文件大小通過size()得到。當前訪問到的數據所在文件中的位置通過pos()完成定位,移動到一個新的位置可以用seek()方法。如果移動到了文件末尾,atEnd()方法將返回true。
①直接讀取文件
QFile file("in.txt"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; while(!file.atEnd()){ QByteArray line = file.readLine(); process_line(line); }
QIODevice::Text告訴Qt編譯器,把Windows風格的行間隔符 \r\n 轉換為 C++風格的 \n。默認情況下,QFile被認為是二進制文件,在讀取過程中並不進行轉換。
②使用Stream讀取文件
QFile file("in.txt"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QTextStream in(&file); while(!in.atEnd()){ QString line = in.readLine(); process_line(line); }
QTextStream會把磁盤中的8bit 數據轉換為16bit 的Unicode QString。默認情況下,編譯器認為認為用戶系統的編碼方式為UTF-8,如果要修改編碼方式,可以調用QTextStream::setCodec()。
③用Stream寫入文件
如果要寫入文本,我們可以用重載運算符 <<,運算符左側是QTextStream對象,右側可以是任意數據類型。
QFile file("out.txt"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; QTextStream out(&file); out << "The magic number is: "<<49<<"\n";
如果用QDataStream讀寫,用法是相似的——我們可以用<<來write,用>>來read。具體用法可以查看QDataStream官方文檔:QDataStream。
當我們使用QFile、QFileInfo、QDir來訪問文件系統時,我們用的是Unicode文件名。在Unix中,這些文件名將被轉換為UTF-8編碼,如果我們想調用標准C++ API(如<cstdio>、<iostream>)去訪問file而非QFile,我們可以用encodeName()和decodeName()在Unicode和UTF-8的file name間互相轉換。
在Unix系統中,有些特殊的系統文件,它們的size()總返回0,但是我們仍能從中讀取許多數據,這些數據在調用read()方法時獲取。此時我們不能用atEnd()來判斷是否讀到了末尾,而只能用readAll()一次讀完,或者重復用read()、readLine()直到沒有數據可讀。下一個例子中,我們用QTextStream按行讀取/proc/modules文件:
QFile file("/proc/modules"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QTextStream in(&file); QString line = in.readLine(); while( !line.isNull() ){ process_line(line); line = in.readLine(); }
最后,需要注意的是QFile是繼承自QIODevice的,而所有read、write的相關方法都是在QIODevice中定義的,所以具體的讀寫方法見QIODevice。
1、模塊和加載項
Header | #include<QFile> |
qmake | QT += core |
Inherits | QFileDevice |
Inherited By | QTemporaryFile |
2、構造
QFile(QString name, QObject *parent) |
QFile(QObject *parent) |
QFile(QString name) |
QFile() |
3、實例方法
返回值類型 |
方法 |
說明 |
bool | copy(const QString &newName) | |
bool | exists() | |
bool | link(const QString &linkName) | |
bool | moveToTrash() | |
bool | open(FILE *fh, QIODevice::OpenMode mode, QFileDevice::FileHandleFlags handleFlags = DontCloseHandle) | |
bool | open(int fd, QIODevice::OpenMode mode, QFileDevice::FileHandleFlags handleFlags = DontCloseHandle) | |
bool | remove() | |
bool | rename(const QString &newName) | |
void | setFileName(const QString &name) | |
QString | symLinkTarget() |
4、靜態方法
方法返回值 |
方法 |
說明 |
bool | copy(const QString &fileName, const QString &newName) | |
QString | decodeName(const QByteArray &localFileName) | |
QString | decodeName(const char *localFileName) | |
QByteArray | encodeName(const QString &fileName) | |
bool | exists(const QString &fileName) | |
bool | link(const QString &fileName, const QString &linkName) | |
bool | moveToTrash(const QString &fileName, QString *pathInTrash = nullptr) | |
bool | permissions(const QString &fileName) | |
bool | remove(const QString &fileName) | |
bool | rename(const QString &oldName, const QString &newName) | |
bool | resize(const QString &fileName, qint64 sz) | |
bool | setPermissions(const QString &fileName, QFileDevice::Permissions permissions) | |
QString | symLinkTarget(const QString &fileName) |
QIODevice
0、說明
QIODevice中實現了Qt中的所有I/O方法,其他用到IO的類如QFile、QBuffer、QTcpSocket,都是從這個類繼承而來。
QIODevice是抽象類,不能實例化,但是可以用多態技術,來定義一個QIODevice去承接一個從它繼承而來的實現類。
在讀寫之前,open()一個文件時必須先設置正確的OpenMode(如ReadOnly或ReadWrite)。之后就可以調用write()、putChar()向其中write,調用read()、readLine()、readAll()來read。完成read、write后調用close()。
有兩種Device:①隨機訪問;②順序訪問。
①隨機訪問:調用seek()轉移到文件中任意位置,調用pos()查看當前位置。QFile、QBuffer是隨機訪問的典型;
②順序訪問:不能從任意位置開始。數據讀取必須一個接一個。QTcpSocket、QProcess是順序訪問的典型。
如何判斷是哪種device呢?調用isSequential()方法。
QIODevice會發射readyRead()當新的數據已經准備好reading,例如,讀取的時候,有新的數據到達網絡或額外的數據被添加到文件中。我們可以調用bytesAvailable()來判斷現在有多少個bytes是准備讀取的。當QTcpSocket程序處理異步數據時,經常會有數據不定時的到達,這時bytesAvailable()通常和readyRead()信號聯用。當有數據要write時,QIODevice會發射bytesWritten()信號,此時用bytesToWrite()可以知道有多少bytes等待寫入。
1、模塊和加載項
Header | #include<QIODevice> |
qmake | QT += core |
Inherits | QObject |
Inherited By | QFileDevice |
2、構造
QIODevice(QObject * parent) | 給Parent構造一個QIODevice |
QIODevice() | 構造一個QIODevice |
3、靜態屬性
類型 |
屬性 |
說明 |
flags | OpenMode | |
enum | OpenModeFlag |
這個enum是用於open()的參數,主要是描述文件打開時采用的device。如果要查看這個device,可以通過openMode()返回。
常用的Mode有ReadOnly、WriteOnly、ReadWrite、Append,對應的device顧名思義。
4、對象方法
返回值類型 |
方法 |
說明 |
virtual bool | atEnd() | 如果當前的read、write位置已經到了device末尾返回true,否則返回false。 在某些系統文件中,atEnd()總是返回false,這種文獻的讀寫可見QFile的說明部分。 |
virtual qint64 | bytesAvailable() | 返回有多少bytes可被讀取。常用於順序讀寫。 |
virtual qint64 | bytesToWrite() | 用於buffer Device,該方法返回有多少bytes正等待write。對於沒有buffer的Device,該方法返回0。 |
virtual bool | canReadLine() | 每當有完整的一行數據可以從device中讀取時返回true,否則false。 對於非buffer Device,該方法返回false。 該方法常和信號readyRead()結合使用。 |
virtual void | close() | 先發送aboutToClose()信號,然后關閉Device並設置它的OpenMode為NotOpen。此外error string也會被重置。 |
void | commitTransaction() | 完成事務讀取。 對於順序Device,保存數據的內部buffer在事務期將被丟棄。 |
int | currentReadChannel() | 返回當前read channel的索引號 |
int | currentWriteChannel() | 返回當前write channel的索引號 |
QString | errorString() | 返回最后一次device error的描述 |
bool | getChar(char *c) | 讀取單個char存到c中,成功時返回true,否則false |
bool | isOpen() |
Device為非NotOpen時返回true,否則false; 如果有data可以從device中讀取時返回true,否則false。常用於檢查Device的Mode是否包含ReadOnly 當Device是順序Device時返回true,否則false 當Text標記開啟時返回true,否則false 如果某個事務正在處理,返回true,否則false 當有數據可以向Device中寫入時返回true,常用於檢查Mode是否包含WriteOnly。 |
virtual bool | open(QIODevice::OpenMode mode) | 打開Device並將它的OpenMode設置為mode。 QFile的open方法重載了它,並且可以同時指定打開文件和Mode |
QIODevice::OpenMode | openMode() | 返回當前Device的Mode,如ReadOnly或WriteOnly |
qint64 | peek(char *data, qint64 maxSize) | 從Device中讀取最多maxSize bytes的數據到data中,並不會改變pos,即pos一直指向讀取開始的位置。返回讀取的bytes數。 發生錯誤時返回-1,沒有可讀數據時返回0。 |
QByteArray | peek(qint64 maxSize) | 從Device中讀取至多maxSize bytes,返回讀取到的數據,類型是QByteArray。 |
virtual qint64 | pos() | 隨機訪問時,返回當前讀寫到的文件位置。 對於順序Device或者關閉的Device,返回0。 當前的 read/write位置會在QIODevice內部維護,所以重載該方法並不是必要的。 |
bool | putChar(char c) | 向Device中寫入單個char,成功時返回true。 |
qint64 | read(char *data, qint64 maxSize) | 從Device中讀取至多maxSize bytes到data中,返回讀取到的bytes數量。錯誤發生時返回-1。 當沒有數據可讀時返回0。 |
QByteArray | read(qint64 maxSize) | 重載方法。 從Device中讀取至多maxSize bytes,返回讀取到的data對應的QByteArray。 發生錯誤時不報錯,只是返回空QByteArray。 |
QByteArray | readAll() | 讀取Device中所有剩余的數據,返回讀到的data對應的QByteArray。 |
int | readChannelCount() | 當Device打開時,返回可用的read channel的數量。 |
qint64 | readLine(char *data, qint64 maxSize) | 從Device中讀取一行ASCII字符,至多maxSize-1 bytes,保存讀取到的數據到data中,返回讀取到的bytes數。 無法讀取時,返回0。發生錯誤時,返回可讀的長度,如果長度為0返回-1。 每次讀取都會在data后邊加一個\0,所以maxSize必須大於1。 讀到以下三種情況時結束:
例如,下面的代碼顯示了如何從一個文件中讀取一行字符: QFile file("box.txt"); if(file.open(QFile::ReadOnly)){ char buf[1024]; qint64 lineLength = file.readLine(buf , sizeof(buf)); if(lineLength != -1){ //當buf中已經讀取到了一行數據 } } 行結束符'\n'也會包含在buffer中。如果沒有讀完一行便到了maxSize - 1,那么該行便不會完整讀入buffer。 |
QByteArray | readLine(qint64 maxSize = 0) | 讀一行,但不超過maxSize個char,將讀取結果以QByteArray形式返回 |
virtual bool | reset() | 重置pos到隨機訪問Device開頭。 需要注意的是,當我們用QTextStream讀取QFile,不能用reset()回到文件頭,而應該用QTextStream::seek() |
void | rollbackTransaction() | 事務回滾。 恢復input stream到startTransaction()調用前。 該方法常用於在提交事務前檢測到未完成read的時候。 |
virtual bool | seek(qint64 pos) | 用於隨機方法Device,該方法重置當前位置到pos。 |
void | setCurrentReadChannel(int channel) | 設置當前QIODevice的read channel為給定的channel,當前的channel常被方法read()、readAll()、readLine()、getChar()調用。當前channel會激發QIODevice發送readyRead()信號。 |
void | setCurrentWriteChannel(int channel) | 設置當前QIODevice的write channel為給定的channel,當前的channel用於方法write()、putChar()。它會激發QIODevice發送bytesWritten()信號。 |
void | setTextModeEnabled(bool enabled) | 如果參數是true,該方法會給Device設置Text標志,否則Text標志會被移除。 該特性對於那些提供了行結尾處理方法的類很有幫助。 |
virtual qint64 | size() | 對於隨機訪問Device,該方法返回Device的大小。 對於順序訪問Device,該方法返回byteAvailable() |
qint64 | skip(qint64 maxSize) | 從文件開頭跳轉到maxSize bytes處。返回實際跳轉的byte數,出錯返回-1。 該方法可以應用到全部Device中,包括隨機訪問和順序訪問。 該方法常和peek()聯合使用,跳過不需要的數據。 對於隨機訪問,它可以跳轉到當前pos之前,負的maxSize是非法的。 |
void | startTransaction() | 在Device上開始一個新的read事務。 該方法會定義一個恢復點。在順序Device中,數據會在內部備份以防止由於恢復導致的不完整的讀取。 在隨機Device,該方法存儲當前pos。調用commitTransaction()、rollbackTransaction()來完成事務。 |
void | ungetChar(char c) | 把單個字符c放回Device中,並后移當前pos。 該方法常用於作為getChar()方法的"undo"方法。 |
virtual bool | waitForBytesWritten(int msecs) | |
virtual bool | waitForReadyRead(int msecs) | |
qint64 | write(char * data, qint64 maxSize) | 從data中寫至多maxSize bytes到Device中,返回實際寫入的bytes數。 發生錯誤時返回-1 |
qint64 | write(char * data) | 把data寫入Device中,返回實際寫入的bytes數。 |
qint64 | write(QByteArray byteArray) | 把byteArray的內容寫到Device中,返回實際寫入的bytes數。 |
int | writeChannelCount() | 當Device為open時返回可用的write channel數量,否則返回0 |
5、信號
信號 |
說明 |
aboutToClose() | 當Device要關閉時發送該信號。 |
bytesWritten(qint64 bytes) | 當有數據已經寫入Device的對應的write channel時發送該信號。 |
channelBytesWritten(int channel, qint64 bytes) | 當有數據已經寫入Device中時發送該信號。 |
channelReadyRead(int channel) | 當有新數據要從Device中可讀的時候發送該信號。 |
readChannelFinished() | 輸入流關閉時發送該信號。 |
readyRead() | 當有新數據要從Device對應的read channel中可讀的時候發送該信號。 |