天天看點

qfile 建立檔案_QT進階之路:檔案資訊類 QFileInfo

本小節内容來自 QFileInfo 類的幫助文檔,QFileInfo 類提供了不依賴具體系統的檔案(指檔案和檔案夾,Unix系統中檔案夾也是算檔案的,下 同)資訊。

QFileInfo 提供關于檔案的名稱、在檔案系統中的位置路徑等資訊,它通路權限資訊、判斷是不是檔案夾或符号連結(快捷方式)等。檔案的大小和最後修改/讀取時間也是可以擷取的。 QFileInfo 還能用于擷取 Qt 程式運作時的内部資源系統檔案資訊。

QFileInfo 既可以根據相對路徑,也可以根據絕對路徑指向一個檔案。絕對路徑總是以檔案系統根打頭(/、C:/、D:/ 等)。相對路徑直接以某個目錄名或檔案名打頭,并指出相對于程式目前工作路徑的位置。絕對路徑例子如 "/tmp/quartz"。相對路徑舉例如 "src/fatlib",這是相對于程式工作路徑的形式。QFileInfo 提供了如下函數判斷目前檔案路徑是否為相對路徑:

bool QFileInfo::​isRelative() const
           

也可以用如下函數,明确地把目前檔案路徑轉為絕對路徑:

bool QFileInfo::​makeAbsolute()
           

makeAbsolute() 函數如果是真的是把相對路徑轉為絕對路徑,那麼傳回 true,如果原本就是絕對路徑,那麼傳回 false。

QFileInfo::​makeAbsolute() 函數傳回值與之前的 QDir::makeAbsolute() 傳回值有差別:之前的 QDir::makeAbsolute() 實際測試總是傳回 true,而 QFileInfo::​makeAbsolute() 如果判斷出原本就是絕對路徑,它會傳回轉換失敗。

QFileInfo 可以在構造函數或者随後用 setFile() 函數指定要通路的檔案,其構造函數如下:

QFileInfo() //無參數,後面可以用 setFile() 函數設定檔案名QFileInfo(const QString & file) //根據相對路徑或絕對路徑的字元串,通路檔案QFileInfo(const QFile & file) //從一個 QFile對象提取該檔案的資訊QFileInfo(const QDir & dir, const QString & file) //根據路徑對象和相對它的檔案名,通路檔案夾資訊QFileInfo(const QFileInfo & fileinfo) //複制構造函數
           

與構造函數參數類似的,setFile() 函數重載有三個:

void QFileInfo::​setFile(const QString & file) //根據相對路徑或絕對路徑通路檔案資訊void QFileInfo::​setFile(const QFile & file) //從已有 QFile 對象提取出檔案資訊void QFileInfo::​setFile(const QDir & dir, const QString & file) //根據路徑對象和相對它的檔案名,通路檔案夾資訊
           

設定好需要通路的檔案名之後,下面就是判斷該檔案有哪些資訊了,首先要判斷是否存在:

bool QFileInfo::​exists() const
           

存在性得到确認之後,才能進行下一步資訊擷取。常見擷取檔案資訊的函數羅列如下:

(1)檔案、目錄、符号連結類型判斷

函數描述bool ​isFile()是否為檔案(不是檔案夾),符号連結指向檔案也算bool ​isDir()是否為檔案夾,符号連結指向檔案夾也算bool ​isSymLink()是否為符号連結(快捷方式)QString ​symLinkTarget()如果是符号連結,就傳回連結指向的原本檔案夾或檔案,否則傳回空串qint64 ​size()傳回檔案大小,如果檔案不存在或者無權限讀取,那麼傳回 0

對于正常的檔案和檔案夾,上面函數意義比較清晰,比較特殊的是符号連結(快捷方式),對于 Unix 系統(含 Linux、Mac OS X),符号連結會由底層作業系統處理,符号連結的 size() 結果等同于連結指向的原本檔案大小,如果用 QFile 打開符号連結,那麼也是打開連結指向的原本檔案。代碼舉例:

#ifdef Q_OS_UNIXQFileInfo info1("/home/bob/bin/untabify");info1.isSymLink(); // returns trueinfo1.absoluteFilePath(); // returns "/home/bob/bin/untabify"info1.size(); // returns 56201info1.symLinkTarget(); // returns "/opt/pretty++/bin/untabify"QFileInfo info2(info1.symLinkTarget());info2.isSymLink(); // returns falseinfo2.absoluteFilePath(); // returns "/opt/pretty++/bin/untabify"info2.size(); // returns 56201#endif
           

"/home/bob/bin/untabify" 是一個符号連結,連結指向的本體檔案是 "/opt/pretty++/bin/untabify" ,符号連結的檔案大小等同于原本檔案的大小。這裡可以另外學到一個知識,通過判斷宏 Q_OS_UNIX,可以知道目前作業系統是不是 Unix 系列的。

對于 Windows 系統裡的快捷方式,即 *.lnk 檔案實體,size() 函數傳回該實體 *.lnk 檔案的大小,而不是連結指向的本體檔案大小。如果用 QFile 打開 *.lnk 檔案,那也是打開快捷方式檔案自身,而不是打開連結指向的本體檔案,這點與 Unix 系統不同,需要注意。代碼舉例:

#ifdef Q_OS_WINQFileInfo info1("C:Documents and SettingsBob甥瑮扡ify.lnk");info1.isSymLink(); // returns trueinfo1.absoluteFilePath(); // returns "C:/Documents and Settings/Bob/untabify.lnk"info1.size(); // returns 743info1.symLinkTarget(); // returns "C:/Pretty++/untabify"QFileInfo info2(info1.symLinkTarget());info2.isSymLink(); // returns falseinfo2.absoluteFilePath(); // returns "C:/Pretty++/untabify"info2.size(); // returns 63942#endif
           

info1 構造函數裡使用的是本地化路徑分隔符,注意 C++ 裡面字元串中 "" 是轉義字元,如果表示反斜杠自己,字元串中需要用 "" 表示一個反斜杠。

(2)路徑檔案名解析

擷取 QFileInfo 對象裡面的完整路徑檔案名,可以通過如下函數:

QString QFileInfo::​filePath() const //含路徑和檔案名,可能是相對的,也可能是絕對的路徑檔案名QString QFileInfo::​absoluteFilePath() const //傳回絕對路徑檔案名QString QFileInfo::​canonicalFilePath() const //傳回權威路徑檔案名
           

canonicalFilePath() 會對多餘的 "."、".."、"/" 做規約,如果是 Unix 符号連結就傳回本體檔案的絕對路徑檔案名。

如果隻擷取路徑部分,而不帶檔案名,使用如下函數:(和剛才三個對比,函數名裡有 "file" 字樣的,傳回結果才帶有檔案名)

QString QFileInfo::​absolutePath() const //傳回絕對路徑目錄,不含檔案名QString QFileInfo::​canonicalPath() const //傳回權威路徑目錄,不含檔案名
           

canonicalPath() 是類似的做規約,但隻傳回路徑部分,而不帶檔案名。

完整的路徑檔案名是可以拆解開來的,可以劃分為路徑和檔案名自身:

QString QFileInfo::​path() const //傳回目前路徑檔案名前面的路徑部分QString QFileInfo::​fileName() const //傳回檔案名部分
           

舉例:

① 檔案 "/tmp/archive.tar.gz" 為例,path() 傳回 "/tmp" ,fileName() 傳回 "archive.tar.gz" 。② 如果 QFileInfo 對象裡面的完整路徑檔案名是以分隔符 ('/') 結尾,比如 "/home/suse132/" ,那麼 path() 傳回 "/home/suse132" ,​fileName()傳回的是空串。③ 如果完整檔案名是 "/home/suse132" ,那麼 path() 傳回 "/home" ,fileName() 傳回 "suse132" 。
           

注意這兩個函數是不檢查檔案或檔案夾是否存在,它們就是單純地拆解完整檔案名為兩個部分而已,它們将最後一個路徑分隔符左邊的歸為路徑 path(),右邊的歸為檔案名 fileName()。如果末尾就是分隔符,那麼檔案名 fileName() 為空。

Qt 類庫中涉及到傳回檔案夾路徑(分 區根路徑除外)的函數,傳回的字元串一般不帶拖尾的路徑分隔符 '/' ,如果需要在檔案夾路徑字元串末尾添加分隔符,可以自己用代碼添加一個。

對于去除路徑的檔案名,比如 "archive.tar.gz" ,還可以進一步進行拆解:

QString QFileInfo::​baseName() const //去除所有擴充名,得到基本名,如 "archive"QString QFileInfo::​completeSuffix() const //全部的擴充名,如 "tar.gz"
           

也就是說 baseName() + completeSuffix() == 原檔案名。

檔案名還有另一種拆解方式:

QString QFileInfo::​suffix() const //最後一個擴充名,如 "gz"QString QFileInfo::​completeBaseName() const //去除最後一個擴充名的前面部分,如 "archive.tar"
           

這裡的 completeBaseName() + suffix() == 原檔案名。

(3)通路權限判斷

關于檔案的建立時間、修改時間,讀、寫、執行權限,所屬使用者、組别以及詳細權限資訊等,可以用下表中的函數擷取:

qfile 建立檔案_QT進階之路:檔案資訊類 QFileInfo

如果希望同時判斷某個檔案的多項權限資訊,可以通過專門的權限判斷函數:

bool QFileInfo::​permission(QFile::Permissions permissions) const

參數 permissions 可以是多項權限枚舉标志的按位或運算結果,同時判斷該檔案是否同時具有這些權限:

qfile 建立檔案_QT進階之路:檔案資訊類 QFileInfo

說明一下,QFileInfo 類和 QFile 類都可以判斷這些權限,而 QFileDevice 是 QFile 的基類。

表格中前面 9 個都是從 Unix 系統引入權限表示方法,對于 Unix、Linux、Mac OS X 系統這些權限比較重要,對于 Windows 基本不用檢查這些權限。

最後 3 個權限 ReadUser、WriteUser、ExeUser 是與程式關系密切的,與系統平台無關,是 Qt 自創的,用于判斷目前程式是否能對該檔案有讀、寫、可執行權限。

如果要同時判斷目前程式是否對某個檔案有讀、寫、執行權限,可以用下面代碼:

QFileInfo fi("/usr/bin/ping");qDebug()<
           

Windows 系統一般判斷讀寫權限(ReadUser | WriteUser)就行了,因為隻有特定擴充名的檔案才能運作。

而在 Unix 系統中,任意擴充名的檔案都可以當可執行檔案來運作。

如果要擷取目前檔案所具有的全部通路權限,可以用如下函數統一擷取:

QFile::Permissions QFileInfo::​permissions() const
           

注意 permissions() 多了一個字母 s,而且沒有參數。它的傳回值就是檔案具備的所有權限,傳回值與上面表格列舉的權限枚舉常量做按位或運算,就可 以判斷分别有哪些權限。

對于 Unix 系列的作業系統,上面權限判斷預設都是啟用的,對于 Windows 的 NTFS 分區,情況不一樣。

對于 NTFS 分區的檔案,因為性能原因 ,Qt 對檔案所屬關系(ownership)和通路權限(permissions)的檢查預設沒有開啟。如果需要開啟對 NTFS 分區檔案的所屬關系和權限檢查,那麼首先手動定義:

extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
           

開啟權限檢查就執行下面這句代碼:

qt_ntfs_permission_lookup++; // 開啟權限檢查
           

關閉權限檢查就執行下面的:

qt_ntfs_permission_lookup--; // 重新關閉權限檢查
           

(4)性能問題

一些 QFileInfo 的函數需要查詢真實的檔案系統,比如 canonicalPath() 、absolutePath()是需要查詢真實路徑位置的,會查詢檔案系統。

而另外一些函數隻通路 QFileInfo 對象自己儲存的資料,比如 path() 函數并不會查詢檔案系統,它隻把内部存的路徑檔案名拆分一下,傳回路徑部分。

也就是說,與 QDir 類似, QFileInfo 對象可以處理不存在的虛假路徑檔案名,隻用于解析檔案名等用途。

注意:為了優化運作效率,QFileInfo 對象會将上次查詢的真實檔案資訊做緩存。如果上次查詢後,真實檔案被修改了,以前緩存的資訊可能是舊的,沒更新。

可以通過重新整理函數消除舊的緩存資訊:

void QFileInfo::​refresh()
           

如果不希望 QFileInfo 對象緩存以前查詢的資訊,可以通過如下函數設定:

void QFileInfo::​setCaching(bool enable)
           

轉載自:https://qtguide.ustclug.org/