文件操作是應用程序必不可少的部分。Qt 作為一個通用開發庫,提供了跨平台的文件操作能力。從本章開始,我們來了解下 Qt 的文件以及輸入輸出的功能,也就是 I/O 系統。
Qt 通過QIODevice提供了對 I/O 設備的抽象,這些設備具有讀寫字節塊的能力。下面是 I/O 設備的類圖:
Qt4
Qt5
從上面的類圖可以看出,Qt4 和 Qt5 在 I/O 設備部分大同小異。只不過 Qt5 新增加了一個QFileDevice類。途中所涉及的類及其用途簡要說明如下:
QIODevice:所有 I/O 設備類的父類,提供了字節塊讀寫的通用操作以及基本接口;QFlie:訪問本地文件或者嵌入資源;QTemporaryFile:創建和訪問本地文件系統的臨時文件;QBuffer:讀寫QByteArray;QProcess:運行外部程序,處理進程間通訊;QAbstractSocket:所有套接字類的父類;QTcpSocket:TCP協議網絡數據傳輸;QUdpSocket:傳輸 UDP 報文;QSslSocket:使用 SSL/TLS 傳輸數據;QFileDevice:Qt5新增加的類,提供了有關文件操作的通用實現。
這其中,QProcess、QTcpSocket、QUdpSoctet和QSslSocket是順序訪問設備。所謂“順序訪問”,是指它們的數據只能訪問一遍:從頭走到尾,從第一個字節開始訪問,直到最后一個字節,中途不能返回去讀取上一個字節;QFile、QTemporaryFile和QBuffer是隨機訪問設備,可以訪問任意位置任意次數,還可以使用QIODevice::seek()函數來重新定位文件訪問位置指針。
本章將主要介紹QFile及其相關類,后面的章節則開始介紹有關輸入輸出的流。
在所有的 I/O 設備中,文件 I/O 是最重要的部分之一。因為我們大多數的程序依舊需要首先訪問本地文件(當然,在雲計算大行其道的將來,這一觀點可能改變)。QFile提供了從文件中讀取和寫入數據的能力。Qt5 新加入的QFileDevice類,則將這部分公共操作放到了這個單獨的類中。顯然,這部分代碼在 Qt4 中位於QFile類。這樣看來,Qt5 的代碼結構更為清晰,層次更好。
我們通常會將文件路徑作為參數傳給QFile的構造函數。不過也可以在創建好對象最后,使用setFileName()來修改。QFile需要使用 / 作為文件分隔符,不過,它會自動將其轉換成操作系統所需要的形式。例如 C:/windows 這樣的路徑在 Windows 平台下同樣是可以的。
QFile主要提供了有關文件的各種操作,比如打開文件、關閉文件、刷新文件等。我們可以使用QDataStream或QTextStream類來讀寫文件,也可以使用QIODevice類提供的read()、readLine()、readAll()以及write()這樣的函數。值得注意的是,有關文件本身的信息,比如文件名、文件所在目錄的名字等,則是通過QFileInfo獲取,而不是自己分析文件路徑字符串。
下面我們使用一段代碼來看看QFile的有關操作:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Open file failed.";
return -1;
} else {
while (!file.atEnd()) {
qDebug() << file.readLine();
}
}
QFileInfo info(file);
qDebug() << info.isDir();
qDebug() << info.isExecutable();
qDebug() << info.baseName();
qDebug() << info.completeBaseName();
qDebug() << info.suffix();
qDebug() << info.completeSuffix();
return app.exec();
}
|
在這段代碼中,我們首先使用QFile創建了一個文件對象。這個文件名字是 in.txt。如果你不知道應該把它放在哪里,可以使用可以使用app.applicationFilePath();或者app.applicationDirPath();來獲得應用程序的執行路徑。只要將這個文件放在同執行路徑一致的目錄下即可。QDir::currentPath()來獲得應用程序執行時的當前路徑。只要將這個文件放在與當前路徑一致的目錄下即可。然后,我們使用open()函數打開這個文件,打開形式是只讀方式,文本格式。這個類似於fopen()的 r 這樣的參數。open()函數返回一個 bool 類型,如果打開失敗,我們在控制台輸出一段提示然后程序退出。否則,我們利用 while 循環,將每一行讀到的內容輸出。
程序的第二部分,我們使用QFileInfo獲取有關該文件的信息。QFileInfo有很多類型的函數,我們只舉出一些例子。比如這里,isDir()檢查該文件是否是目錄;isExecutable()檢查該文件是否是可執行文件等。baseName()可以直接獲得文件名;suffix()則直接獲取文件后綴名。我們可以由下面的示例看到,baseName()和completeBaseName(),以及suffix()和completeSuffix()的區別:
|
1
2
3
4
5
|
QFileInfo fi("/tmp/archive.tar.gz");
QString base = fi.baseName(); // base = "archive"
QString cbase = fi.completeBaseName(); // base = "archive.tar"
QString ext = fi.suffix(); // ext = "gz"
QString ext = fi.completeSuffix(); // ext = "tar.gz"
|


