天天看點

c++ qt擷取電腦的記憶體_QT進階之路:目錄浏覽類 QDir

本小節内容主要來自 QDir 類的幫助文檔,Qir 類用于通路檔案系統中的目錄結構和檔案等。QDir 類的靜态函數通常用于擷取程式運作時系統相關的一些路徑資訊等,而對于具體某一個目錄的操作,需要建立 QDir 對象來實作。

QDir 用于操作路徑檔案名,通路關于目錄路徑、檔案等資訊,操作真實的底層檔案系統。同時,QDir 的功能對 Qt 程式運作時的内部資源系統也是通用的,内部資源系統以 ":/" 為根目錄。

Qt 都是以 '/' 作為統一的路徑分隔符,網際網路上也是用 '/' 作為 URL 分隔符的。Qt 程式員應當總是使用 '/' 作為路徑分隔符,而不用管作業系統原本的路徑分隔符是什麼。Qt 會自動把自己的路徑檔案名轉換為底層檔案系統可接受的形式,進而操作底層檔案系統。

QDir 既可以接受相對檔案路徑,也可以接受絕對檔案路徑。相對檔案路徑通常不以檔案系統根打頭,而絕對路徑總是以檔案系統根打頭,比如 C:/、D:/ 、/ 等等(從這裡開始都使用 Qt 預設的路徑分隔符)。相對路徑的基準目錄通常是應用程式的工作路徑,比如 QtCreator 調試運作程式時,就以影子建構目錄作為基準目錄,其他情況通常是以可執行程式所在的目錄為準。

絕對路徑舉例:

QDir("/home/user/Documents")QDir("C:/Documents and Settings")
           

第一個絕對路徑是 Unix/Linux 系統裡的形式,第二個絕對路徑是 Windows 裡的形式。Qt 代碼裡面都是使用 '/' ,作為路徑分隔符,底層檔案系統的本地路徑分隔符不用操心,交給 Qt 自己處理就行了。

相對路徑舉例:

QDir("images/landscape.png")
           

QDir 對象可以通過函數 isRelative() 判斷自己包含的路徑是否為相對路徑,通過函數 isAbsolute() 判斷自己包含的路徑是否為絕對路徑形式。另外可以通過 makeAbsolute() 函數

bool QDir::​makeAbsolute()
           

把自己的路徑确切地轉換為絕對路徑,這樣後續操作的意義更為明确。

下面将 QDir 類的接口函數按照功能進行大緻的分類講解:

(1)導航和目錄操作

QDir 構造函數可以指定該對象的起始浏覽目錄:

QDir(const QDir & dir)QDir(const QString & path = QString())QDir(const QString & path, const QString & nameFilter, SortFlags sort = SortFlags( Name | IgnoreCase ), Filters filters = AllEntries)
           

第一個構造函數是複制另一個 QDir 對象。第二個是以路徑字元串構造 QDir 對象,這也是最常用的構造函數,如果參數裡字元串是空的,那麼就以應用程式目前工作目錄 "." 作為起始目錄。第三個構造函數可以指定檔案名過濾字元串 nameFilter、排序方式 sort ,以及檔案類型過濾枚舉 filters 。

構造好 QDir 對象之後,就可以擷取該對象目前處于的目錄:

QString QDir::​path() const //可能是相對路徑,也可能是絕對路徑QString QDir::​absolutePath() const //一定傳回絕對路徑如果要重新設定 QDir 對象的路徑,那麼可以通過如下函數設定:void QDir::​setPath(const QString & path)
           

注意 ​setPath() 函數是不檢查參數 path 是否存在,也不管是不是有 "./../.." 之類複雜的相對路徑形式,是以調用該函數可能進入一個不存在的目錄,如果進一步操作可能導緻出錯,需要在調用該函數之前用 ​exists() 判斷參數裡的路徑是否存在:

bool QDir::​exists(const QString & name) const //參數裡既可以判斷檔案夾,也可以判斷檔案的存在性bool QDir::​exists() const //不帶參數,判斷 QDir 對象自身路徑是否為存在的檔案夾,隻管檔案夾!
           

第一個帶參數的 ​exists(const QString & name) 函數,既可以判斷檔案夾的存在性,也可以判斷檔案的存在性。

第二個隻針對 QDir 對象自身路徑是否為實際檔案夾進行判斷,如果 QDir 對象自身路徑是一個存在的檔案,那麼也會傳回 false,隻有是真實的檔案夾 才傳回 true。

QDir 對象可以用 dirName() 傳回該層級目錄的簡短名字,不包含路徑,通常就是絕對路徑的最後一個子串:

QDir("Documents/Letters/Applications").dirName() //傳回 "Applications"如果 QDir 構造函數裡字元串為空,那麼 dirName() 傳回目前目錄 "." :QDir().dirName() //傳回 "."除了 QDir 構造函數和 setPath() 函數,更常用的修改 QDir 對象目前目錄位置的函數是 cd():bool QDir::​cd(const QString & dirName)
           

cd() 函數比 setPath() 函數更智能,應該盡量用 cd() 函數,因為 cd() 函數會自動檢查參數裡的目錄是否存在,如果參數裡路徑不存在,那麼該函數傳回 false,QDir 對象原本的路徑不變;如果切換目錄成功就傳回 true,并進 入新目錄。

QDir 對象有切換到父目錄的快捷函數:bool QDir::​cdUp()
           

切換成功就傳回 true(有父目錄);切換失敗就傳回 false(沒父目錄,原本已經到根了)。

QDir對象不僅能通路檔案夾,還能在自己目前的目錄裡面進行建立、重命名和删除的操作:

bool QDir::​mkdir(const QString & dirName) const //建立新目錄bool QDir::​rename(const QString & oldName, const QString & newName) //重命名舊的目錄bool QDir::​rmdir(const QString & dirName) const //删除一個空目錄
           

這些操作如果成功就傳回 true,失敗就傳回 false。注意:

​mkdir() 參數裡的檔案路徑不能是已經有的(建立已有的會傳回失敗),必須是新的;

​rename() 參數裡,舊的目錄名 oldName 必須存在,新的目錄名 newName 不能與已有的重名;

rmdir() 函數隻能删除空檔案夾,如果檔案夾裡面有其他檔案或子檔案夾就不能删除。

操作失敗的原因,還有可能是沒有權限,因為 Unix/Linux 普通使用者經常沒有寫權限,這些操作就容易失敗。對于 Unix/Linux 普通使用者,應該隻操作自己有寫入權限的 /home 路徑裡面的檔案夾和檔案。

對于遞歸建立新的長路徑,QDir 提供了快捷函數:

bool QDir::​mkpath(const QString & dirPath) const
           

dirPath 可以是長路徑,比如 "/home/suse132/Projects/a/b/c" ,對于路徑上已有的檔案夾"/home/suse132/",不會構造新的,而後半部不存在的 "Projects/a/b/c" ,該函數會逐級遞歸建立新檔案夾,直到 "/home/suse132/Projects/a/b/c" 每一個層級檔案夾都存在。如果建立成功或者 dirPath 已經存在,都會傳回 true,建立失敗就傳回 false。

​mkpath() 函數的逆操作函數是:

bool QDir::​rmpath(const QString & dirPath) const
           

注意 ​rmpath() 隻能删除空的檔案夾,如果參數裡是 "Projects/a/b/c",隻要其中有一層的檔案夾裡面有其他子檔案夾或檔案,都會操作失敗。 而 且不要以絕對路徑為參數調用rmpath() 函數,因為檔案系統根總是存在的,不能删除,不要這麼幹!

QDir對象可以對自己目錄裡的一些屬性進行判斷,比如:

bool QDir::​exists(const QString & name) const //子檔案夾或檔案是否存在bool QDir::​isReadable() const //QDir對象目前目錄是否有讀權限,Linux系統有些目錄普通使用者不能讀取bool QDir::​isAbsolute() const //QDir對象目前目錄是否為絕對路徑bool QDir::​isRelative() const //QDir對象目前目錄是否為相對路徑bool QDir::​isRoot() const //QDir對象目前目錄是否為檔案系統根一般 QDir 對象會對先前的檔案系統狀态有個緩存,如果在程式運作時檔案系統改變了,可以通過如下函數重新整理一下緩存,重新通路檔案系統:void QDir::​refresh() const
           

(2)檔案和目錄内容枚舉

目錄裡面可以包含一大堆條目,每個條目可以是檔案、子檔案夾、符号連結(快捷方式)等,目錄裡面的條目計數為:

uint QDir::​count() const
           

如果要擷取 QDir 對象目前目錄所有子條目名稱字元串清單,使用函數:

QStringList QDir::​entryList(Filters filters = NoFilter, SortFlags sort = NoSort) constQStringList QDir::​entryList(const QStringList & nameFilters, Filters filters = NoFilter, SortFlags sort = NoSort) const
           

函數參數裡的 filters 是指條目類型的過濾枚舉類型,sort 是指傳回的條目清單的排序方式;第二個 ​entryList() 函數裡的 nameFilters 是指條目名稱的過濾字元串清單 。這幾個參數都有專門對應的設定函數,等會再講。entryList() 函數傳回的字元串清單列印出來就是得到的檔案、子檔案夾、符号連結(快捷方式)名字。

目前目錄裡的子條目當然不僅僅有名字,還有其他很多屬性,比如檔案類型、大小、修改日期、讀寫屬性等等,單個檔案或檔案夾的詳細資訊是用 QFileInfo 對象表示的,從 QDir 對象的目錄枚舉出所有子條目詳細資訊的函數為:

QFileInfoList QDir::​entryInfoList(Filters filters = NoFilter, SortFlags sort = NoSort) constQFileInfoList QDir::​entryInfoList(const QStringList & nameFilters, Filters filters = NoFilter, SortFlags sort = NoSort) const
           

​entryInfoList() 函數的參數同上面 ​entryList() 的參數,隻是傳回結果為 QFileInfo 的清單 QFileInfoList 。QFileInfoList 清單當作數組來用就行了,序号從 0 到 count()-1 ,每個條目對應一個檔案或子檔案夾或符号連結。

在不過濾的情況下,entryList() 和 entryInfoList() 傳回的清單包含 "." 和 ".." 目錄,一個點代表目前目錄自己,兩個點代表父目錄。

注意 QDir 對象内部存儲的目前目錄,可以是真實存在的路徑,也可以是虛假的不存在路徑:

◆ 實際存在的目前目錄通常用于枚舉或通路真實子檔案夾、檔案等,可以用 ​exists(const QString & name) 函數判斷子檔案 夾或檔案是否存在。

◆ 對于不存在的目前目錄,QDir 對象也可以照常工作,但因為不存在,是以枚舉子條目肯定是空的。如果 QDir 對象裡面存儲的是不存在的目前目錄,那麼通常用于構造路徑字元串,用于下一步建構路徑,比如用于 mkpath() 函數。

根據 QDir 對象裡的目前目錄,配合 filePath() 和 absoluteFilePath() 函數可以構造出檔案的路徑,這些路徑可以是都不存在的,也可以是真實的,也是用 ​exists() 函數判斷存在性,以下面代碼為例:

QDir directory("Documents/Letters");

QString path = directory.filePath("contents.txt"); QString absolutePath = directory.absoluteFilePath("contents.txt"); qDebug()<如果程式的工作路徑(QtCreator調試運作程式時為影子建構目錄)為
           
D:QtProjectsch02build-hellocreator-Desktop_Qt_5_4_0_MinGW_32bit-Debug
           

實際上在這個路徑裡,根本沒有 "Documents/Letters" 這兩級子目錄,上面代碼還會正常工作,它就是分别計算檔案 "contents.txt" 的相對于 QDir 對象的相對路徑,以及 "contents.txt" 檔案的絕對路徑,上面一段代碼的結果就是:

false"Documents/Letters/contents.txt""D:/QtProjects/ch02/build-hellocreator-Desktop_Qt_5_4_0_MinGW_32bit-Debug/Documents/Letters/contents.txt"
           

這些路徑其實都不存在,filePath() 和 absoluteFilePath() 函數僅僅是拼接出檔案的完整路徑,而不管它存在或不存在。

在使用 QDir 對象時,一定要用 exists() 函數謹慎判斷路徑是否真實存在!

如果要删除一個已存在的檔案,使用如下函數:

bool QDir::​remove(const QString & fileName)
           

删除成功就傳回 true,如果沒有該檔案或者沒有删除權限等,删除失敗傳回 false。

删除一個空目錄用之前說過的 ​rmdir() 函數。

下面講講枚舉子條目時的過濾和排序,除了可以直接在 ​entryList() 和 ​entryInfoList() 指定各個參數,還可以用專門的函數設定這兩個函數用到的參數:

①名稱字元串過濾設定

void QDir::​setNameFilters(const QStringList & nameFilters)
           

nameFilters 是針對子條目名稱的過濾串,參考幫助文檔主題 QRegExp wildcard matching 的内容,常用的就是 *,比對任意個數字元,比如

QStringList filters; filters << "*.cpp" << "*.cxx" << "*.cc"; dir.setNameFilters(filters);
           

這段代碼就是過濾後得到 "*.cpp" 、 "*.cxx" 、 "*.cc" 三個擴充名的源代碼檔案。

QDir 類另外提供了一個靜态函數,用于判斷某個檔案名是否比對某個名稱過濾串:

bool QDir::​match(const QString & filter, const QString & fileName) //靜态函數
           

②類型權限等過濾設定

void QDir::​setFilter(Filters filters)
           

這個 filters 與條目名稱無關,它判斷的是條目類型,Filters 枚舉常量很多,根據 QDir 的幫助文檔列舉如下:

c++ qt擷取電腦的記憶體_QT進階之路:目錄浏覽類 QDir

一般對于條目類型,使用預設的不過濾即可,如果确定要過濾為僅檔案或僅檔案夾,可以用上面的枚舉常量進行篩選。QDir::Readable、 QDir::Writable 、QDir::Executable 是 Unix/Linux 系統裡常見的權限劃分,需要與 QDir::Dirs 或者 QDir::Files 做按位或 | ,結合使用。

③排序設定

void QDir::​setSorting(SortFlags sort)
           

這個參數決定 ​entryList() 和 ​entryInfoList() 傳回清單的排序方式,SortFlags 排序的枚舉常量如下:

c++ qt擷取電腦的記憶體_QT進階之路:目錄浏覽類 QDir

注意前四個排序常量隻能四選一,不能同時運用。一般在前四個選一個作為排序标準,後面的枚舉常量與前面四選一的做 | 運算,後面的枚舉常量就可以同時生效。

無論是通過上面三個設定函數專門設定,還是直接在 ​entryList() 和 ​entryInfoList() 指定各個參數,都是可行的,效果是等價的。

(3)應用程式工作路徑和其他特殊路徑

這部分都是 QDir 類的靜态函數,屬于該應用程式自己的全局設定,這些靜态函數傳回 QDir 對象或 QString 字元串,列舉如下:

c++ qt擷取電腦的記憶體_QT進階之路:目錄浏覽類 QDir

其中應用程式自己的工作路徑是可以改的:

bool QDir::​setCurrent(const QString & path)
           

其他的路徑一般都是系統定死的,Qt 是不修改其他三個路徑的。

應用程式的工作路徑不等于可執行程式所在的目錄,比如 QtCreator 調試運作程式時,工作路徑是影子建構目錄。擷取可執行程式所在的目錄使用另一個類的靜态函數:

QString QCoreApplication::​applicationDirPath() //靜态函數
           

聯合 QDir::​setCurrent() 和 QCoreApplication::​applicationDirPath() 就可以把程式的工作路徑設定為與可執行檔案相同的路徑:

QDir::setCurrent( QCoreApplication::applicationDirPath() ); qDebug()<<:currentpath>
           

把上面代碼放到主界面的構造函數裡就能在程式運作時自動修改工作路徑。

如果要擷取檔案系統根的清單,使用 QDir::​drives() 靜态函數,之前 Windows 和 Linux 檔案系統截圖都提到這個函數:

QFileInfoList QDir::​drives() //靜态函數
           

對于 Windows 系統,一般有多個檔案系統根,如 C:/ ,D:/ 等等,對于 Unix 和 Linux 系統,隻有一個根 / 。

(4)路徑操作和字元串

相對路徑中經常包含一些 "." 代表目前目錄,".." 代表父目錄,還有一些符号連結(快捷方式)指向其他真實檔案。

Qt 提供了如下函數對這些進行處理規約,得到絕對權威路徑:

QString QDir::​canonicalPath() const //會自動判斷路徑是否真實存在
           

如果規約後的目前路徑是不存在的,那麼該函數傳回空串,如果規約後的目前路徑是真實存在的,就傳回最簡化的絕對權威路徑。

另一個弱化版的靜态規約函數是 cleanPath(),它不檢查路徑是否真實存在,也不管是不是符号連結(快捷方式),它隻對 "." 、 ".." "/" 等做規約處理,去掉備援的點号和斜杠:

QString QDir::​cleanPath(const QString & path) //靜态函數
           

在特殊場合,可能需要将 Qt 統一的路徑字元串形式與作業系統本地化的檔案路徑形式進行互相轉換,QDir 提供一對靜态函數實作這個轉換:

QString QDir::​fromNativeSeparators(const QString & pathName) //靜态函數,從本地化路徑串轉為 Qt 風格路徑串QString QDir::​toNativeSeparators(const QString & pathName) //靜态函數,将 Qt 風格路徑串轉為本地化路徑串
           

關于 QDir 類的内容介紹就到這,最後小節的檔案浏覽示例是用最簡單的接口,也不排序和過濾,就按照預設的參數列舉檔案夾和檔案,等到下一章學到表格控件時再做排序和過濾方面的功能。

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