Qt:QFile、QIODevice


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()UnicodeUTF-8file 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(如ReadOnlyReadWrite)。之后就可以調用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並設置它的OpenModeNotOpen。此外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()

isReadable()

isSequential()

isTextModeEnabled()

isTransactionStarted() 

isWritable()

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。

讀到以下三種情況時結束:

  1. 第一個\n
  2. 讀到maxSize - 1 bytes;
  3. 檢測到Device data末尾。

例如,下面的代碼顯示了如何從一個文件中讀取一行字符:

    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中可讀的時候發送該信號。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM