1. 程式人生 > >使用QFile進行檔案操作(QFile可以使用FILE *指標,還必須指定AutoCloseHandle)

使用QFile進行檔案操作(QFile可以使用FILE *指標,還必須指定AutoCloseHandle)

QFile類我我們提供了操作檔案的常用功能。它是一種io裝置,可以用來讀寫文字檔案和二進位制檔案,也可以用來讀寫Qt的資原始檔。QFile類可以單獨使用,該類本身提供了read/write函式,但更方便的方式是,將QFile和QTextStream或QDataStream一起使用。

一般情況下,使用QFile建立物件時,就會把要操作的檔名傳遞給它。但該類也提供了一個setFileName() 方法,允許我們在任何時候為QFile物件設定要操作的檔名。但是,QFile 只支援"/",不支援"\"。

在構造QFile的物件後,我們可以使用exists() 判斷檔案是否存在,使用remove() 刪除一個檔案。在進行實際的內容讀寫前,需呼叫open()開啟檔案,讀寫結束後,要呼叫close()關閉檔案,也可以寫呼叫一下flush(),沖刷緩衝區。就向我們剛才說的,我們一般使用QDataStream或QTextStream 讀寫檔案,但我們也可以使用QFile繼承自QIODevice的函式,如read()、readLine()、readAll()、write()等。除了讀寫函式外,我們還能使用size() 函式獲得檔案的大小;使用pos() 或 seek() 函式獲取及設定檔案讀寫的位置;使用atEnd() 函式判斷是否到達了檔案結尾。

直接使用QFile讀寫檔案

QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;

while (!file.atEnd()) {
QByteArray line = file.readLine();
process_line(line);
}
在此,我們將QIODevice::Text傳給了open()函式,該標誌是用來告訴Qt將檔案中的換行符由"\r\n",轉換成"\n"。因為,預設情況下,QFile把檔案當做二進位制進行讀寫,不會進行任何的位元組轉換。
使用流讀取檔案:

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。預設情況下,QTextStream假定檔案使用的是使用者系統的本地8bit編碼。我們也可以使用QTextStream::setCodec() 函式還改變這種行為。
當使用QFile,QFileInfo和QDir類去操作檔案系統時,你可以使用Unicode編碼的檔名。在Unix平臺上,這些檔名會被轉換成8-bit編碼。但如果你想使用標準c++ API或者平臺特定的API去訪問檔案,那麼你可以使用encodeName() 和 decodeName() 函式在Unicode檔名和8-bit檔名之間進行轉換。

在Unix平臺下,存在一些特殊的系統檔案,例如/proc目錄下,對這個檔案呼叫size() 總是返回0,然而,你還是能夠從此類檔案中讀取到資料;這些資料是為了相應你的read() 函式而間接產生出來的。但是,在這種情況下,你不能使用atEnd() 來判斷是否還有資料可讀(因為atEnd() 對於大小為0的檔案返回true)。相反,你應該呼叫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繼承的open() 函式外,QFile本身也為我們提供了兩個open() 函式:

bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags = DontCloseHandle)
bool open(int fd, OpenMode mode, FileHandleFlags handleFlags = DontCloseHandle)

第一個open() 會按一定的模式開啟一個現存的檔案指標。同時,可以再指定額外的標誌。如下程式碼所示:
#include <stdio.h>

void printError(const char* msg)
{
QFile file;
file.open(stderr, QIODevice::WriteOnly);
file.write(msg, qstrlen(msg)); // write to stderr
file.close();
}
當一個QFile已這種方式開啟時,那麼後續的close() 函式的作用會受到AutoCloseHandle標誌的影響。如果指定了該標誌,並且這個open() 函式呼叫成功了,那麼後續再QFile物件上呼叫close() 會關閉底層檔案控制代碼。否則,若沒指定這個標誌,close()函式不會真正的關閉底層檔案控制代碼,而只是沖刷 了一下緩衝區。如下測試程式碼所示:
#include <QCoreApplication>
#include <QFile>
#include <cstdio>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

FILE *pf = fopen("test.txt", "wb");
if(pf == nullptr)
return 0;
QFile file;
file.open(pf, QIODevice::WriteOnly); //1
//file.open(pf, QIODevice::WriteOnly, QFileDevice::AutoCloseHandle); //2
file.write("hello");
file.close();
fwrite("world", strlen("world"), 1, pf);

return a.exec();
}
當我們使用 1處的方式開啟檔案指標,即不指定AutoCloseHandle標誌,則close() 函式後的“world”是可以繼續被寫入檔案的;若使用2處的方式開啟檔案指標,則“world”並不會再被寫入檔案,因為底層檔案已關閉。

第二個open() 函式與此類似,只不過其是按一定模式開啟一個現存的檔案描述符。AutoCloseHandle標誌也會影響後續的close()函式。同時,如果QFile已這種方式開啟,那麼它會被自動地設定為raw mode,這意味著檔案的輸入、輸出函式的執行會變慢。如果你遇到了效能問題,你應該嘗試使用其他的開啟函式。

至於其他的成員函式,比如檔案的刪除、重新命名,檔案訪問許可權的設定,Qt的幫助文件已講的很清除,大家可以在使用時隨時檢視即可。
---------------------
作者:求道玉
來源:CSDN
原文:https://blog.csdn.net/Amnes1a/article/details/65434670
版權宣告:本文為博主原創文章,轉載請附上博文連結!