天天看點

C++ 檔案、資料夾、路徑處理函式庫:boost::filesystem

原帖:https://tokyo.zxproxy.com/browse.php?u=uG7kXsFlW1ZmaxKEvCzu8HrCJ0bXIAddA1s5dtIUZ%2FYzM1u9JI7jjKLTXvXJlIqeavUo1Ak%3D&b=6

而前面也有提到,目前的 Boost 1.44 預設還是使用 FileSystem v2,是以如果要使用 FileSystem v3 的話,除了要 include FileSystem 的主要 header 檔:boost/filesystem.hpp 外,還要再 include 他之前,加上一行:

來指定要使用的 FileSystem 版本。理論上等到 Boost 1.45 後,應該就不必加這個了。

而由於 FileSystem 這個函式庫是需要是先編譯的,是以在建置有使用到 FileSystem 的程式時,也需要 link FileSystem 的 library 檔。在 VC 的環境下的話,理論上 Boost 會自動去 link,使用者隻要設定好路徑就可以了;gcc 的話,則是要加上「-l boost_filesystem」來做 library 的 linking。

在操作上,FileSystem 主要是定義了一個 path 的類別,用來處理路徑的操作;像是透過 operator / 可以輕鬆地來加上子目路的路徑、透過 pareant_path() 則可以簡單地取得上一層路徑。同時,Path 也可以快速地和 std::string 做轉換,是以在使用上相當地友善~

下面就是一些簡單的 Path 操作範例:

執行的結果應該會向下面這樣:

在這個範例裡,可以發現 FileSystem 的 Path 在操作上相當簡單,除了可以直接透過 std::string 來建立 Path 的物件外,Boost 也提供了轉換的函式,在大部分情況下都可以把 std::string 自動轉換成 Path 的型別。而如果要進到子資料夾,隻要透過 operator / 就可以了(上方黃底的部分)~在操作上相當地直覺。

而如果想把 Path 轉換為 std::string 的話,也隻要呼叫他提供的 Path::string() 這個函式(或者也有提供 wstring() 的版本)就可以了;下面就是一個簡單的例子:

函式

說明

Windows 範例

Linux 範例

root_name()

根目錄名稱

C:

root_directory()

根目錄資料夾

\

/

root_path()

根目錄路徑

C:\

relative_path()

相對路徑

Windows\System32\xcopy.exe

Build/heresy/a.out

parent_path()

上一層目錄路徑

C:\Windows\System32

/Build/heresy

filename()

檔案名稱

xcopy.exe

a.out

stem()

不包含副檔名的檔名

xcopy

a

extension()

副檔名

.exe

.out

基本上,對於要解析一個路徑來說,這邊提供的函式應該算是相當充分了~

bool exists( const path& )

判斷所指定的路徑是否存在

bool is_directory( const path& )

判斷指定的路徑是否是目錄

bool is_regular_file( const path& )

判斷指定的路徑是否是一般檔案

bool is_symlink( const path& )

判斷指定的路徑是否是 symbolic link

bool is_other( const path& )

判斷指定的路徑是否不是路徑、一般檔案或 symbolic link

bool is_empty( const path& )

判斷指定路徑是否是空目錄、或是大小為零的檔案

uintmax_t file_size( const path& )

取得指定路徑檔案的大小,隻對 regular file 有用

註:這些函式實際上都是用 file_status 來進行操作的,傳入 path 當參數的隻是 inline 函式

void copy_file( const path& from, const path& to)

複製檔案。 也可以再加上額外的 copy_option,來指定檔案已存在時的處理方法(fail_if_exists、overwrite_if_exists)。

void rename( const path& old, const path& new )

修改檔案、目錄的名稱。

bool create_directories( const path& )

bool create_directory( const path& )

建立新目錄。 create_directory() 在上層目錄不存在的情況下,會建立失敗;而 create_directories() 則會一層一層地建立下來。

bool remove( const path& )

uintmax_t remove_all(const path& p)

刪除檔案或目錄。 remove() 隻會刪除單一檔案和目錄,如果目錄內還有東西,會刪除失敗;remove_all() 則是會把目錄內的東西也一起刪除掉。

path current_path()

void current_path( const path& )

取得、設定目前的工作路徑

bool equivalent(const path& , const path& )

確認兩個路徑是否相同

space_info space( const path& )

取得路徑的容量、可用空間資訊

path unique_path();

產生一個獨一無二的路徑名稱。形式可以指定,預設的形式會式「%%%%-%%%%-%%%%-%%%%」,每一個「%」都會被填入隨機產生的值,適合用在產生暫存性的路徑名稱。

基本上,有了這些函式,應該就足以應付絕大部份檔案、路徑操作上的需求了!當然,Heresy 這邊沒有全列,而實際上 boost 的 FileSystem 對於某些檔案系統的特殊功能,也沒有完全支援;而如果要用到 FileSystem 沒有支援的功能,可能就得用系統提供的功能了。

下面是一個簡單的例子,他會列出 C:\windows 下所有的檔案與資料夾:

在這個例子裡,基本上就是透過一個 for 迴圈、以及透過 p1 建立出來的 directory_iterator it,來掃整個 p1 目錄下的項目。其中,directory_iterator( p1 ) 就是建立一個指向 p1 目錄下第一個項目的 iterator、directory_iterator() 則是建立一個通用的、代表結尾的 end iterator,用來做中斷條件的判斷參考。而在使用上,由於 it 的型別實際上是 directory_iterator,是以還是需要轉型成 path,才友善做一般性的操作;或者,也可以透過 status() 這個函式,來取得檔案狀態進行操作。

如此就可以根據副檔名來做排序了~不過這個寫法非常簡略,是以其實還是有不少改善的空間的。 ^^"

最後,則是來貼一個 Heresy 自己寫的程式當作範例。這個程式會去遞迴地去掃描所給的資料夾下的所有的資料夾以及檔案,並且根據檔案大小來做排序(非 regular file 會放到最後);而輸出的部分,如果是檔案的話,他除了印出檔名外,也會印出檔案的大小。

基本上,這也就隻是個簡單的範例程式了~實用價值不高,而且應該也還有許多改善的空間。 ^^"