使用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
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

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



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