boost.png (6897 bytes) Filesystem 庫
Boost Home    Library Home    Tutorial    Reference   FAQ

參考文檔

目錄

簡介
定義
要求
    對 程序的要求
    對 實現的要求
頭文件 <filesystem> 概要
Path traits
類模板 basic_path
    路 徑名格式
    路 徑名語法
    文 件名轉換
    要 求
 類模板 basic_path (續)
            basic_path 構造函數
            basic_path 賦值
            basic_path 修改器
            basic_path 操作符
            basic_path 觀察器
            basic_path 迭代器
            basic_path 非成員函數
            basic_path 插入器和提取器
        類模板 basic_filesystem_error
            basic_filesystem_error 構造函數
            basic_filesystem_error 觀察器
        類模板 basic_directory_entry
            basic_directory_entry 構造函數
            basic_directory_entry 修改器
            basic_directory_entry 觀察器
            basic_directory_entry 比較操作
Filesystem 庫 (續)
        類模板 basic_directory_iterator
            basic_directory_iterator 構造函數
        類模板 basic_recursive_directory_iterator
        類 file_status
非成員操作函數
    狀 態函數
    謂 詞函數
    屬 性函數
    其 它操作函數
    便 利函數
對頭文件 <fstream> 的增加
<fstream> 實現的建議
路徑分解表
鳴謝
參考
 

本庫早期版本中的有些函數已經改名或不再使用。請見 不再使用的名稱和特性

簡介

本庫的有些行為是通過引用 ISO/IEC 9945:2003, POSIX 來規定的。這些行為如何實現則並沒有規定。

[註:這為與操作系統相關的行為的實現制定了一個"類似"規則。大概這些實現通常都會調用 原生的操作系統API. --注完]

實現被鼓勵,但不要求,支持 POSIX 所定義的行為。實現應該對與 POSIX 定義的行為有所不同的行為給出文檔說明。實現如果由於操作系統和文件系統的局限,而不能支持精確的 POSIX 行為,則應盡量提供接近 POSIX 的合理行為。如果一個實現不能提供任何合理的行為,該實現應該以實現定義的方式報告一個錯誤。

[註:這類錯誤可能通過一個 #error 指示, 一個 static_assert, 一個 basic_filesystem_error 異常, 一個特定的返回值,或其它方式來報告。--注完]

特定的操作系統,如 OpenMVS, UNIX, 和 Windows 僅在示範或給出實現指導時提及。不提及其它操作系統是有意的。

在本參考手冊中給出的函數的 效果後置條件 可能不適用於 競爭條件 的情形。這類診斷並不被要求。

如果可能存在競爭條件,使得程序在調用函數之前測試某個前提條件變得不可靠,則不指定這樣的 Requires. 反之,這些條件被指定為 Throws 條件。

[註:作為一個設計實踐,如果要求一個程序在調用函數之前檢查前提條件是不合理的,則這些 前提條件不會被規定。 -- 注完]

定義

在本參考手冊中,使用了以下定義:

文件:一個對 象,可以寫入、讀出或兩者俱可。文件具有確定的屬性,包括類型。文件類型包括有:普通文件、符號鏈接和目錄。實現還可能支持其它文件類型。

文件系統:一 組文件和它們的屬性。

文件名:文 件的名字。其格式由 POSIX 文 件名Filename 基本定義所指定。

路徑:一組元 素序列,用以標識文件系統中的某個位置。這些元素是 root-name, root-directory, 以及各個連續的文件名。請見 路徑名語法

路徑名:表 示一個路徑的一個字符串。

鏈接:一個目 錄項對象,它關聯某個文件的文件名。在某些文件系統中,多個目錄項可以關聯同一個文件名。

硬鏈接:到 一個已有文件的鏈接。有些文件系統支持同一個文件的多個硬鏈接。如果最後一個硬鏈接被刪除,則文件本身被刪除。

[註:硬鏈接可以被視為一個文件的所有權共享智能指針-- 注完]

符號鏈接:一 種文件類型,在路徑名解析過程中使用,文件中保存的字符串被用於修改路徑名的解析。

[註:符號鏈接可以被視為一個文件的原始指針。如果被指向的文件不存在,則該符號鏈接被稱 為 "懸空" 的符號鏈接-- 注完]

斜線符: 字符 '/', 也稱為斜線分隔符。

點符: 字符 '.', 也稱為句點。

競爭條件:當 多個線程、進程或計算機交錯訪問和修改文件系統中的同一個對像時發生的情形。

要求

對程序的要求

在本文中名為 Path, Path1, 或 Path2 的模板參數都應為類型 basic_path, 或是派生自 basic_path 一某個類,除非特別說明。

對實現的要求

在本文中,有些函數模板具有名為 Path, Path1, 或 Path2 的模板參數。當以類型為 char* std::string 的參數 s 來調用這些函數時,實現應將這個參數視作為 path(s). 當以類型為 wchar_t*std::wstring 的參數 s 來調用這些函數時,實現應將這個參數視作為 wpath(s). 對於帶兩個參數的函數,實現不應支持將 Path1Path2 作為不同類型來處理。

[註:這個 "do-the-right-thing" 規則允許用戶寫象 exists("foo") 這樣的代碼,利用類 basic_path 的字符串轉換構造函數,而不需要寫又長又容易出錯的 exists(path("foo")). 這對於編寫簡單、類似於腳本的程序尤其重要,這也正是本庫的一個主要應用。以不同類型的兩個參數來調用函數的情況非常罕見,很可能是代碼錯誤,所以這種情 形下的自動轉換是不被支持的。

實現的技術並不特別規定。以 exists() 為例,以下是一種可能的實現技術:

template <class Path>
typename boost::enable_if<is_basic_path<Path>,bool>::type exists(const Path& p);
inline bool exists(const path& p) { return exists<path>(p); }
inline bool exists(const wpath& p) { return exists<wpath>(p); }

對於C字符串或 std::basic_string 參數,enable_if 將會失敗,這樣就會通過適當的 basic_path 轉換構造函數自動轉換為 basic_path 對象。-- 注完]

這 兩個重載沒有在正式文本中給出,是因為:

本文中的函數的實現可以調用由操作系統系統提供的API. 如果調用這些操作系統API產生了錯誤,則實現應通過拋出 basic_filesystem_error 異常來報告錯誤,除非特別說明。

[註:這些異常及其拋出條件不會在本文的每一個 Throws 單元中說明。因為在文件系統操作中,硬件錯誤、網絡失敗、競爭條件和其它多種錯誤都會常常發生,用戶應該知道,除非特別說明,任何的文件系統操作,無論看 起來多麼沒有危險,都可能會拋出異常。-- 注完]

對 於那些常常用在錯誤不被視為異常的環境中的函數,都有其它重載,接受一個額外的參數 error_code& ec. 這些函數重載不拋出異常。如果發生了錯誤,ec 將被設置為操作系統所報告的錯誤碼,否則 ec 被設為 0. 如果沒有類型 error_code& ec 參數的重載是返回 void 的,則另一個重載(帶有類型 error_code& ec 參數的)將返回一個 error_code,值為 ec.

頭文件 <boost/filesystem> 概要

  namespace boost
{
namespace filesystem
{
template <class String, class Traits> class basic_path;

template<class String, class Traits>
void swap(basic_path<String, Traits> & lhs, basic_path<String, Traits> & rhs);

template<class String, class Traits> bool operator<(a a, b b);
template<class String, class Traits> bool operator==(a a, b b);
template<class String, class Traits> bool operator!=(a a, b b);
template<class String, class Traits> bool operator>(a a, b b);
template<class String, class Traits> bool operator<=(a a, b b);
template<class String, class Traits> bool operator>=(a a, b b);
template<class String, class Traits> bool operator/(a a, b b);

template<class Path>
basic_ostream<typename Path::string_type::value_type, typename Path::string_type::traits_type> &
operator<<(basic_ostream<typename Path::string_type::value_type, typename Path::string_type::traits_type>& os, const Path & ph);

template<class Path>
basic_istream<typename Path::string_type::value_type, typename Path::string_type::traits_type> &
operator>>(basic_istream<typename Path::string_type::value_type, typename Path::string_type::traits_type>& is, Path & ph);

struct path_traits;
struct wpath_traits;

typedef basic_path<std::string, path_traits> path;
typedef basic_path<std::wstring, wpath_traits> wpath;

template<class Path> struct is_basic_path;

template<class Path> struct slash { static const char value = '/'; };
template<class Path> struct dot { static const char value = '.'; };
template<class Path> struct colon { static const char value = ':'; };

class filesystem_error;

template <class Path> class basic_filesystem_error;

typedef basic_filesystem_error<path> filesystem_error;
typedef basic_filesystem_error<wpath> wfilesystem_error;

template <class Path> class basic_directory_entry;

typedef basic_directory_entry<path> directory_entry;
typedef basic_directory_entry<wpath> wdirectory_entry;

template <class Path> class basic_directory_iterator;

typedef basic_directory_iterator<path> directory_iterator;
typedef basic_directory_iterator<wpath> wdirectory_iterator;

template <class Path> class basic_recursive_directory_iterator;

typedef basic_recursive_directory_iterator<path> recursive_directory_iterator;
typedef basic_recursive_directory_iterator<wpath> wrecursive_directory_iterator;

enum file_type { status_unknown, file_not_found, regular_file, directory_file,
symlink_file, block_file, character_file, fifo_file, socket_file,
type_unknown
};

class file_status;

struct space_info // returned by space function
{
uintmax_t capacity;
uintmax_t free;
uintmax_t available;
};

// status functions
template <class Path> file_status status(const Path& p);
template <class Path> file_status status(const Path& p, error_code& ec);
template <class Path> file_status symlink_status(const Path& p);
template <class Path> file_status symlink_status(const Path& p, error_code& ec);

// predicate functions
bool status_known( file_status s );
bool exists( file_status s );
bool is_regular_file( file_status s );
bool is_directory( file_status s );
bool is_symlink( file_status s );
bool is_other( file_status s );

template <class Path> bool exists(const Path& p);
template <class Path> bool is_directory(const Path& p);
template <class Path> bool is_regular_file(const Path& p);
template <class Path> bool is_other(const Path& p);
template <class Path> bool is_symlink(const Path& p);
template <class Path> bool is_empty(const Path& p);

template <class Path1, class Path2>
bool equivalent(const Path1& p1, const Path2& p2);

// attribute functions
template <class Path> Path current_path();
template <class Path> void current_path(const Path& p);
template <class Path> const Path& initial_path();
template <class Path> uintmax_t file_size(const Path& p);
template <class Path> space_info space(const Path& p);
template <class Path> std::time_t last_write_time(const Path& p);
template <class Path>
void last_write_time(const Path& p, const std::time_t new_time);

// operations functions
template <class Path> bool create_directory(const Path& dp);
template <class Path1, class Path2>
void create_hard_link(const Path1& old_fp, const Path2& new_fp);
template <class Path1, class Path2>
error_code create_hard_link(const Path1& old_fp, const Path2& new_fp, error_code& ec);
template <class Path1, class Path2>
void create_symlink(const Path1& old_fp, const Path2& new_fp);
template <class Path1, class Path2>
error_code create_symlink(const Path1& old_fp, const Path2& new_fp, error_code& ec);
template <class Path> bool remove(const Path& p);
template <class Path1, class Path2>
void rename(const Path1& from_p, const Path2& to_p);
template <class Path1, class Path2>
void copy_file(const Path1& from_fp, const Path2& to_fp);
template <class Path> Path system_complete(const Path& p);
template <class Path> Path complete(const Path& p, const Path& base=initial_path<Path>());

// convenience functions
template <class Path> bool create_directories(const Path& p);
template <class Path> typename Path::string_type extension(const Path& p);
template <class Path> typename Path::string_type basename(const Path& p);
template <class Path>
Path change_extension(const Path& p, const typename Path::string_type& new_extension);

} // namespace filesystem
} // namespace boost

Path traits

這一節定義了對表示路徑行為的 traits 類的要求,並且定義了兩個類,分別滿足對基於 string 和 wstring 的路徑的這些要求。還定義了幾個額外的 path traits 結構模板,以及這些模板的特化。

在本文中定義的類模板 basic_path 要求一些其它的類型、值和行為來完成對其語義的定義。

從作用上說,Traits 的行為就像它是一個帶有一個被初始化為 false 的私有成員 bool m_locked,以及一個已初始化的成員 std::locale m_locale 的類。

路徑行為 Traits 要求
表 達式 要 求
Traits::external_string_type 一個 typedef,它是 basic_string 的一個特化。其 value_type 為操作系統用於表示路徑名的字符類型。
Traits::internal_string_type 一個 typedef,它是 basic_string 的一個特化。其 value_type 為程序用於表示路徑名的字符類型。要求它與 basic_path 的 String 模板參數具有相同類型。
Traits::to_external( p, is ) is, 被 m_locale codecvt facet 轉換為 external_string_type.
Traits::to_internal( p, xs ) xs, 被 m_locale codecvt facet 轉換為 internal_string_type.
Traits::imbue(loc) 作用:如果 m_locked, 則拋出異常。否則 m_locked = true; m_locale = loc;
返回:void
拋出:basic_filesystem_error
Traits::imbue(loc, std::nothrow) 作用:如果  (!m_locked) 則 m_locale = loc; bool temp(m_locked); m_locked = true;
返回:temp

類型 is_basic_path 應該是一個 UnaryTypeTrait (TR1, 4.1). 其主模板應直接或間接派生自 std::tr1::false_type. 類型 is_basic_path 應針對 path, wpath, 和任何用戶專有 basic_path 類型進行特化,而且這些特化都應直接或間接派生自 std::tr1::true_type.

結構模板 slash, dot, 和 colon 用於提供類型為 char 的值。如果某個用戶專有 basic_path 具有不可由 char 轉換而得的 value_type 類型,則模板 slashdot 應被特化,以提供某種可轉換為 basic_path::value_type 的類型的值。

類模板 basic_path

類模板 basic_path 提供了一個在C++程序中表示 路徑paths 的可移植機制,它使用可移植的通用路徑名語法。當不需要可移植性時,可以使用原生文件系統的特定 格式。類模板 basic_path 只關心路徑的詞法和語法方面。該路徑不要求在操作系統的文件系統中存在,也可能包含某些當前操作系統認為無效的名字。

[註:如果本庫的函數只能使用C++或C風格的字符串,那麼它們的可移植性只是幻想,因為 雖然函數調用的語法是可移植的,但函數所操作的字符串的語義卻不可移植。-- 注完]

  namespace boost
{
namespace filesystem
{
template <class String, class Traits> class basic_path
{
public:
typedef basic_path<String, Traits> path_type;
typedef String string_type;
typedef typename String::value_type value_type;
typedef Traits traits_type;
typedef typename Traits::external_string_type external_string_type;

// constructors/destructor
basic_path();
basic_path(const basic_path& p);
basic_path(const string_type& s);
basic_path(const value_type* s);
template <class InputIterator>
basic_path(InputIterator first, InputIterator last);

~basic_path();

// assignments
basic_path& operator=(const basic_path& p);
basic_path& operator=(const string_type& s);
basic_path& operator=(const value_type* s);
template <class InputIterator>
basic_path& assign(InputIterator first, InputIterator last);

// modifiers
basic_path& operator/=(const basic_path& rhs);
basic_path& operator/=(const string_type& s);
basic_path& operator/=(const value_type* s);
template <class InputIterator>
basic_path& append(InputIterator first, InputIterator last);

void clear();
void swap( basic_path & rhs );

basic_path& remove_filename();
basic_path& replace_extension(const string_type & new_extension = "");

// observers
const string_type string() const;
const string_type file_string() const;
const string_type directory_string() const;

const external_string_type external_file_string() const;
const external_string_type external_directory_string() const;

string_type root_name() const;
string_type root_directory() const;
basic_path root_path() const;
basic_path relative_path() const;

basic_path parent_path() const;
string_type filename() const;

string_type stem() const;
string_type extension() const;

bool empty() const;
bool is_complete() const;
bool has_root_name() const;
bool has_root_directory() const;
bool has_root_path() const;
bool has_relative_path() const;
bool has_filename() const;
bool has_parent_path() const;

// iterators
class iterator;
typedef iterator const_iterator;

iterator begin() const;
iterator end() const;

};

} // namespace filesystem
} // namespace boost

一個 basic_path 對象可以保存空路徑。保存路徑的內部形式並不指定。

在本文中描述的訪問文件及其屬性的函數要將 一個 basic_path 對像解析為文件層次中的一個特定文件。路徑名被合適地轉換為操作系統所要求的字符串類型、格式和編碼,按 POSIX Pathname Resolution 機制進行解析。結果路徑名的編碼由 Traits::to_external 轉換函數決定。

[註:並不保證保存在 basic_path 對像中的路徑對於特定的操作系統或文件系統是有效的。-- 注完]

本文中有些函數返回的 basic_path 對像部分或全部由得自操作系統的路徑名組成。這些路徑名被從由操作系統提供的真實格式和字符串類型進行合適的轉換。結果路徑的編碼由 Traits::to_internal 轉換函數決定。

那些返回 "const string_type" 或 "const external_string_type" 的成員函數,允許被實現為分別返回 "const string_type&" 或 "const external_string_type&"。

[註:這允許實現避免不必要的複製。指定以常量值返回可以確保在轉換為以引用返回的實現時 不會破壞已有程序。-- 注完]

路徑名格式

有兩種格式的字符串或字符序列參數來表示一個路徑:

所 有 basic_path 的描述路徑的字符串或字符序列參數都接受可移植路徑名格式,也接受由原生格式轉義序列前綴"//:"顯式標識的原生格式。

[註:"//:"被選擇 作為轉義序列,是因為在POSIX中"//"是由實現 定義的,":"則是不允許用於Windows 文件,而且在任何系統中如果想表示以":"開頭的文件名,可以使用單個"/"。以上因素一起消除了這個轉義序列與某個真實文件名發生衝突的可能。-- 注完]

如 果在文字上可以區分開,實現最好可以直接接受原生的路徑名格式。每個實現應該在文檔中寫明是否可以直接接受原生路徑名格式。

[例如:

-- OpenVMS: "SYS1::DISK1:[JANE.TYLER.HARRY]" 被視為帶有系統名、驅動器名和三個目錄文件名的原生路徑名,而不是某個文件名的可移植路徑名。

-- Windows: "c:\\jane\\tyler\\harry" 被視為帶有驅動器名、根目錄和三個文件名的原生路徑名,而不是某個文件名的可移植路徑名。

-- 反例1: 某個操作系統允許在文件名中使用"/",它使用"."作為目錄分隔符。區分可移植格式和原生格式的字符串或字符序列是不可能的,如果沒有其它可區分的語 法。所以實現不接受原生格式的路徑名,除非指定一個原生參數。

-- 反例2: 某個操作系統允許在文件名中使用"/",它使用一些不常見的字符作為目錄分隔符。這時實現不能接受不帶有額外的原生參數的原生格式路徑名,原生參數必須被 用於在文件名中含有"/"的原生格式參數。

-- 舉例完]

[註:鴨 子規則duck-rule ("如果某個東西看起來像鴨子,走起來像鴨子,叫進來象鴨子,那麼它就是一隻鴨子")消除了源自程序員錯誤和支持要求的格式混亂。-- 注完]

如果可以同時接受可移植格式和原生格式,則實現應該在文檔中說明哪些字符或字符序列被用作區分可移植格式和原生格式。

[註:Windows 實現被鼓勵將":"和"\"定義為區分原生格式和可移植格式的字符。--注完]

路徑名語法

可移植路徑名格式的語法如下:

pathname:
            root-nameopt root-directoryopt relative-pathopt

root-name:
            implementation-defined

root-directory:
            slash
            root-directory slash
            implementation-defined

relative-path:
            filename
            relative-path slash
            relative-path slash filename

filename:
            name
            dot
            dot dot

slash:
            slash<Path>::value

dot:
            dot<Path>::value

該語法是參照 POSIX 的 Filename, Pathname Pathname Resolution 定義的。該語法與 POSIX 間的任何衝突都不是故意的。本技術報告遵守 POSIX.

以 上表達形式取自於 POSIX, 後者在多次使用該方式引向 C 標準。

[註:Windows 實現被鼓勵將"//name" 定義為可允許的 root-name. POSIX 允許但不要求相關實現也這樣做。Windows 實現被鼓勵定義另一個 root-directory 元素 root_directory name. 它只適用於 root-name 的 "//name" 格式。

Windows 實現被鼓勵在 name 前加一個":"作為原生格式的 root-name, 將"\"作為與"/"等價的格式元素。-- 注完]

文件名轉換

在將文件轉換為原生操作系統格式時,建議但不要求實現將無效字符或字符序列轉換為有效的字符或字符序列。這些轉換是由實現定義的。

[註:文件轉換給了程序和文件名更大的可移植能力。

建議實現基於已有標準或實踐之上進行轉換。相關例子包括URL的轉義語法,即在百分號('%') 後跟兩位十六進制數字來表示字符值。在 OpenVMS, 不允許在文件名中出現百分號,所以使用美元符('$') 後跟兩位十六進制數字,還有將小寫字母轉為大寫。-- 注完]

Windows 平台上的Boost實現目前不進行無效字符映射。來自LWG的未決反饋是,Boost可能決定用 % hex hex 作為轉義序列。如果是這樣,是否會有標準化的建議?

要求

名為 String 的模板參數的實參應該是一個含有與類模板 basic_string 相同名字、類型、值和語義的成員的類。

名為 Traits 的模板參數的實參應該是一個滿足 路徑行為 Traits 要求 表中給出的要求的類。

名為 InputIterator 的模板參數的實參應該滿足輸入迭代器的要求(C++標準,24.1.1,Input iterators [lib.input.iterators]),並且應該具有可以轉換為 basic_path::value_type 的值類型。

有些帶有 InputIterator 模板參數的函數模板還有其它非模板的重載形式。如果 InputIterator 的類型不是 path_format_t, 則實現應該只選擇函數模板的重載。

[註:"do-the-right-thing" 規則確保用戶期望的重載會被選中。實現的技術並未規定 - 具體實現可以使用 enable_if 或者其它技術來實現這一效果-- 注完]

basic_path 構造函數

basic_path();

後置條件: empty().

basic_path(const string_type& s);
basic_path(const value_type * s);
template <class InputIterator>
basic_path(InputIterator s, InputIterator last);

備註: 字符串 s 及字符序列 [first,last) 的格式在 路徑名格式 中說明。

作用: 保存字符串 s 或字符序列 [first,last) 中的路徑元素。

basic_path 賦值

basic_path& operator=(const string_type& s);
basic_path& operator=(const value_type* s);
template <class InputIterator>
basic_path& assign(InputIterator first, InputIterator last);

備註: 字符串 s 及字符序列 [first,last) 的格式在 路徑名格式 中說明。

作用: 保存字符串 s 或字符序列 [first,last) 中的路徑元素。

返回: *this

basic_path 修改器

basic_path& operator/=(const basic_path& rhs);

作用: 將保存在 rhs 中的路徑增加到保存的路徑中。

返回: *this

basic_path& operator/=(const string_type& s);
basic_path& operator/=(const value_type* s);
template <class InputIterator>
basic_path& append(InputIterator first, InputIterator last);

備註: 字符串 s 及字符序列 [first,last) 的格式在 路徑名格式 中說明。

作用: 將字符串 s 或字符序列 [first,last) 中的路徑元素增加到保存的路徑中。

返回: *this

void clear();

後置條件: this->empty() 為真。

void swap( basic_path & rhs );

作用: 交換兩個路徑的內容。

拋出: 無。

後置條件: this->string() 包含與 rhs.string() 相同的字符序列, rhs.string() 則包含與 this->string() 相同的字符序列。

複雜度: 常量時間。

basic_path& remove_filename();

作用: 如果 has_parent_path() 則從保存的路徑中刪除最後的 filename. 如果路徑中剩下的最後的一個或多個"/"不是表示根 目錄,就刪除它們。

返回:*this

[注: 該函數對於高效實現 basic_directory_iterator 是必須的。它被設為公有的,可用於其它用途。-- 注完]

basic_path& replace_extension( const string_type & new_extension = "" );

後置條件:extension() == replacement, 其中 replacementnew_extension 如果 new_extension.empty() || new_extension[0] == '.',否則 replacement 為'.'後跟 new_extension

返回:*this

basic_path 觀察器

由 分解函數所返回的值的示例請見 路徑分解表

const string_type string() const;

返回: 所保存的路徑,按照 路徑名語法 規則進行格式化。

const string_type file_string() const;

返回: 所保存的路徑,按照操作系統關於常規文件路徑名的規則進行格式化,帶 文件名轉換

[注: 對於某些操作系統,包括 POSIX Windows, 常規文件和目錄的路徑名的原生格式是相同的,所以 file_string()directory_string() 返回相同的字符串。但是在 OpenMVS 上,表達式 path("/cats/jane").file_string() 返回字符串 "[CATS]JANE"path("/cats/jane").directory_string() 則返回字符串 "[CATS.JANE]". -- 注完]

const string_type directory_string() const;

返回: 所保存的路徑,按照操作系統關於目錄路徑名的規則進行格式化,帶 文件名轉換

const external_string_type external_file_string() const;

返回: 所保存的路徑,按照操作系統關於常規文件路徑名的規則進行格式化,帶 文件名轉換,並由 Traits::to_external 轉換函數進行編碼。

const external_string_type external_directory_string() const;

返回: 所保存的路徑,按照操作系統關於目錄路徑名的規則進行格式化,帶 文件名轉換,並由 Traits::to_external 轉換函數進行編碼。

string_type root_name() const;

返回: root-name, 如果所保存的路徑中包含 root-name, 否則返回 string_type().

string_type root_directory() const;

返回: root-directory, 如果所保存的路徑中包含 root-directory, 否則返回 string_type().

如果 root-directory 由"/"加 name 組成,則"/"被排除在返回字符串之外。

basic_path root_path() const;

返回: root_name() / root_directory()

basic_path relative_path() const;

返回: 從被保存的路徑組成的 basic_path, 如果有則返回 root-path 加上第一個 filename。 否則返回空的 basic_path.

string_type filename() const;

返回: empty() ? string_type() : *--end()

basic_path parent_path() const;

返回: (string().empty() || begin() == --end()) ? path_type("") : br, 其中 br 是這樣構成的:以一個空的 basic_path 開始,對 begin(), --end() 間的每個元素相繼應用 operator/=

string_type stem(const Path & p) const;

返回: 如果 p.filename() 包含一個'.',則返回 p.filename() 中從開頭起至最後一個'.'的子串(不包含'.')。否則,返回 p.filename()

string_type extension(const Path & p) const;

返回: 如果 p.filename() 包含一個'.',則返回 p.filename() 中從最右一個'.'起至末尾的子串。否則,返回一個空串。

[注: 返回值中是包含'.'的,所以可以區分 無擴展名和空擴展名。

具體實現可以允許但不要求為那些在擴展名上增加其它元素,如數據流或分區數據集名,的文件系統定義額外的行為。 -- 注完]

bool empty() const;

返回: string().empty().

bool is_complete() const;

返 回: true, 如果 root_path() 的元素唯一地標識了一個目錄,否則返回 false.

bool has_root_path() const;

返回: !root_path().empty()

bool has_root_name() const;

返回: !root_name().empty()

bool has_root_directory() const;

返回: !root_directory().empty()

bool has_relative_path() const;

返回: !relative_path().empty()

bool has_leaf() const;

返回: !leaf().empty()

bool has_branch_path() const;

返回: !branch_path().empty()

basic_path 迭代器

basic_path::iterator 是一個常量迭代器,它滿足雙向迭代器(C++ 標準, 24.1.4 Bidirectional iterators [lib.bidirectional.iterators])的所有要求。它的 value_typestring_type.

對一個 basic_path 對象的任何非常性成員函數的調用將 使得引向該對像元素的所有迭代器均失效。

前向遍歷的順序如下:

後向遍歷的順序與前向遍歷相反。

iterator begin() const;

返回: 一個指向上述遍歷列表中第一個有效元素的迭代器。如果沒有這樣的元素,返回結束迭代器。

iterator end() const;

返回: 結束迭代器。

basic_path 非成員函數

template<class String, class Traits>
void swap( basic_path<String, Traits> & lhs, basic_path<String, Traits> & rhs )

作用: lhs.swap( rhs )

basic_path 非成員操作符

basic_path 有七個非成員操作符(/, ==, !=, <, >, <=, >=), 每個操作符有五個重載。為簡單起見,以表格形式給出規格說明。得到的35個函數簽名中的每一個都是一個模板,其模板參數列表為 template<class String, class Traits>. 這些參數的格式在 路徑名格式 中描述。

參數類型重載

basic_path<String, Traits>& a, basic_path<String, Traits>& b
const typename basic_path<String, Traits>::string_type& a, basic_path<String, Traits>& b
const typename basic_path<String, Traits>::string_type::value_type* a, basic_path<String, Traits>& b
const basic_path<String, Traits>& a, typename basic_path<String, Traits>::string_type& b
const basic_path<String, Traits>& a, typename basic_path<String, Traits>::string_type::value_type* b

basic_path 非成員操作符 表中,ab 參數類型重載 表中給出的類型。如果 ab 的類型為 const basic_path<String, Traits>&, 則 a'b' 分別為 ab. 否則 a'b' 分別表示從 a b 構造的有名或無名的 basic_path<String, Traits> 臨時對象。

basic_path 非成員操作符
表 達式 返 回類型 語 義
a / b basic_path<String, Traits> basic_path<String, Traits> tmp(a);
return a /=
b';
a < b bool return lexicographical_compare(a'.begin(), a'.end(), b'.begin(), b'.end());
a == b bool return !(a' < b') && !(b' < a');
a != b bool return !(a' == b');
a > b bool return b' < a';
a <= b bool return !(b' < a');
a >= b bool return !(a' < b');

[注: 路徑等同性和路徑等價性是具有不 同語義的。

等 同性由 basic_path 的非成員 operator== 判定,它只考慮兩個路徑的字面表示。路徑 "abc" 和 "ABC" 是不等同的。

等 價性則由 equivalent() 非成員函數來判定,它根據兩個路徑是否 解析resolve 為同一個文件系統實體來判定。路徑 "abc" 和 "ABC" 可能是也可能不是被解析為同一個文件,這取決於文件系統。

想 要判斷兩個路徑是否"相同"的程序員必須決定這裡所說的"相同"是指"相同的表示法"還是"解析為同一個文件",並據此選擇適當的函數。 -- 注完]

basic_path 插入器和提取器

template<class Path>
basic_istream<typename Path::string_type::value_type, typename Path::string_type::traits_type>&
operator>>(basic_istream< typename Path::string_type::value_type, typename Path::string_type::traits_type>& is,
Path& ph );

作用:  typename Path::string_type str;
       is >> str;
       ph = str;

返回: is

template<class Path>
basic_ostream<typename Path::string_type::value_type, typename Path::string_type::traits_type>&
operator<<(basic_ostream< typename Path::string_type::value_type, typename Path::string_type::traits_type>& os,
const Path& ph );

作用:  os << ph.string()

返回: os

類 模板 basic_filesystem_error

 namespace boost
{
namespace filesystem
{
template <class Path> class basic_filesystem_error : public system_error
{
public:
typedef Path path_type;

explicit basic_filesystem_error(const std::string& what_arg, error_code ec);
basic_filesystem_error(const std::string& what_arg, const path_type& p1, error_code ec);
basic_filesystem_error(const std::string& what_arg, const path_type& p1, const path_type& p2, error_code ec);

const path_type& path1() const;
const path_type& path2() const;

const char * what() const;
};
} // namespace filesystem
} // namespace boost

類模板 basic_filesystem_error 定義了一個被拋出的異常對像類型,它用於報告由本文中所列函數產生的文件系統錯誤。

basic_filesystem_error 構造函數

explicit basic_filesystem_error(const std::string& what_arg, error_code ec);

後置條件:

表達式
runtime_error::what() what_arg.c_str()
code() ec
path1().empty() true
path2().empty() true
basic_filesystem_error(const std::string& what_arg, const path_type& p1, error_code ec);

後置條件:

表達式
runtime_error::what() what_arg.c_str()
code() ec
path1() 一個指向所保存的 p1 拷貝的引用
path2().empty() true
basic_filesystem_error(const std::string& what_arg, const path_type& p1, const path_type& p2, error_code ec);

後置條件:

表達式
runtime_error::what() what_arg.c_str()
code() ec
path1() 一個指向所保存的 p1 拷貝的引用
path2() 一個指向所保存的 p2 拷貝的引用

basic_filesystem_error 觀察器

const path_type& path1() const;

返回: 指向由構造函數所保存的 p1 拷貝的引用,或者如果沒有這樣的拷貝則返回空路徑。

const path_type& path2() const;

返回: 指向由構造函數所保存的 p2 拷貝的引用,或者如果沒有這樣的拷貝則返回空路徑。

const char * what() const;

返回: 一個字符串,包含 runtime_error::what() 及以 code() 作為第一參數調用 system_message() 所得的結果。精確的格式未指定。

實現應該提供一個特化的 template<> const char * basic_filesystem_error<path>::what() const 返回一個字符串,其中包含 runtime_error::what(),code() 作為第一參數調用 system_message() 所得的結果,並且如果非空,則還有 path1().file_string()path2.file_string(). 精確的格式未指定。

實現和用戶都被允許提供 what 成員函數的其它特化。

類模 板 basic_directory_entry

  namespace boost
{
namespace filesystem
{
template <class Path> class basic_directory_entry
{
public:
typedef Path path_type;
typedef typename Path::string_type string_type;

// constructors
basic_directory_entry();
explicit basic_directory_entry(const path_type& p,
file_status st=file_status(), file_status symlink_st=file_status());

// modifiers
void assign(const path_type& p, file_status st=file_status(), file_status symlink_st=file_status());
void replace_filename(const string_type& s, file_status st=file_status(), file_status symlink_st=file_status());

// observers
const Path& path() const;
operator const Path&() const;

file_status status() const;
file_status status(error_code& ec) const;
file_status symlink_status() const;
file_status symlink_status(error_code& ec) const;

// comparisons
bool operator<(const basic_directory_entry<Path>& rhs);
bool operator==(const basic_directory_entry<Path>& rhs);
bool operator!=(const basic_directory_entry<Path>& rhs);
bool operator>(const basic_directory_entry<Path>& rhs);
bool operator<=(const basic_directory_entry<Path>& rhs);
bool operator>=(const basic_directory_entry<Path>& rhs);

private:
path_type m_path; // for exposition only
mutable file_status m_status; // for exposition only; stat()-like
mutable file_status m_symlink_status; // for exposition only; lstat()-like
};

} // namespace filesystem
} // namespace boost

basic_directory_entry 對像保存了一個 basic_path 對象,一個用於非符號鏈接狀態的 file_status 對象,以及一個用於符號鏈接狀態的 file_status 對象。file_status 對像擔當值緩存的角色。

[注: 因為一個路徑名的 status() 可能是一個非常昂貴的操作,有些操作系統以目錄迭代副產品的方式提供狀態信息。緩存這些狀態信息可以顯著地節約時間。在有競爭條件的情況下,緩存與不緩存 的結果可能會有所不同。-- 注完]

對 一個有15,047項的目錄進行迭代,冷啟動狀態下以非緩存方式查詢狀態耗費6秒鐘,而採用緩存方式查詢狀態則只要1秒鐘。測試環境為:Windows XP, 3.0 GHz 處理器,帶一個較快的硬盤。在 Linux 和 BSD-系 Unix 上進行目錄迭代的狀態查詢,也有類似的加速。

basic_directory_entry 構造函數

basic_directory_entry();

後置條件:

表達式
path().empty() true
status() file_status()
symlink_status() file_status()
explicit basic_directory_entry(const path_type& p, file_status st=file_status(), file_status symlink_st=file_status());

後置條件:

表達式
path() p
status() st
symlink_status() symlink_st

basic_directory_entry 修改器

void assign(const path_type& p, file_status st=file_status(), file_status symlink_st=file_status());

後置條件:

表達式
path() p
status() st
symlink_status() symlink_st
void replace_leaf(const string_type& s, file_status st=file_status(), file_status symlink_st=file_status());

後置條件:

表達式
path() path().branch() / s
status() st
symlink_status() symlink_st

basic_directory_entry 觀察器

const Path& path() const;
operator const Path&() const;

返回: m_path

file_status status() const;

作 用: 就像:

if ( !status_known( m_status ) )
{
if ( status_known(m_symlink_status) && !is_symlink(m_symlink_status) )
{ m_status = m_symlink_status; }
else { m_status = status(m_path); }
}

拋 出: 參見 status 函數。

返 回: m_status

file_status status(error_code& ec) const;

作 用: 就像:

if ( !status_known( m_status ) )
{
if ( status_known(m_symlink_status) && !is_symlink(m_symlink_status) )
{ m_status = m_symlink_status; }
else { m_status = status(m_path, ec); }
}
else ec = 0;

返 回: m_status

file_status symlink_status() const;

作 用: 就旬:

if ( !status_known( m_symlink_status ) )
{
m_symlink_status = symlink_status(m_path);
}

拋 出: 參見 symlink_status 函數。

返 回: m_symlink_status

file_status symlink_status(error_code& ec) const;

作 用: 就像:

if ( !status_known( m_symlink_status ) )
{
m_symlink_status = symlink_status(m_path, ec);
}
else ec = 0;

返 回: m_symlink_status

類 模板 basic_directory_iterator

  namespace boost
{
namespace filesystem
{
template <class Path>
class basic_directory_iterator :
public iterator<input_iterator_tag, basic_directory_entry<Path> >
{
public:
typedef Path path_type;

// constructors
basic_directory_iterator();
explicit basic_directory_iterator(const Path& dp);
basic_directory_iterator(const Path& dp, error_code& ec);
basic_directory_iterator(const basic_directory_iterator& bdi);
basic_directory_iterator& operator=(const basic_directory_iterator& bdi);
~basic_directory_iterator();

// other members as required by
// C++ Std, 24.1.1 Input iterators [lib.input.iterators]
};

} // namespace filesystem
} // namespace boost

basic_directory_iterator 符合輸入迭代器的要求(C++ 標準, 24.1.1, Input iterators [lib.input.iterators])。

basic_directory_iterator 從其構造的目錄中持續讀入元素,類似於調用 POSIX readdir_r(). 當一個 basic_directory_iterator 被構造後,每一次調用 operator++, 它讀入並保存一個 basic_directory_entry<Path> 值及其可能帶有的相關狀態值。operator++ 不保持等同性,即:i == j 並不意味著 ++i == ++j.

[注: 不保持等同性的後果是,目錄迭代器只能被用於單次遍歷的算法。-- 注完]

如果到達目錄元素的末尾,迭代器將變為等同於 end 迭代器值。不帶參數的構造函數 basic_directory_iterator() 總是構造一個 end 迭代器對象,它是唯一一個用於結束條件的合法迭代器。一個 end 迭代器的 operator* 結果是未定義的。對於其它迭代器值,則返回一個 const basic_directory_entry<Path>&. 一個 end 迭代器的 operator-> 結果也是未定義的。對於其它迭代器,則返回一個 const basic_directory_entry<Path>*.

兩個 end 迭代器永遠都是相等的。一個 end 迭代器則不會等於一個非-end迭代器。

以上措詞基於標準庫的 istream_iterator 措詞。註釋被縮短並移至註解。

對一個 basic_directory_iterator 進行提領所得的 basic_directory_entry 對象,調用其 path() 成員,將得到一個 basic_path 對象的引用,該對像由構造該迭代器的目錄參數,通過 operator/= 加上目錄項文件名所組成。

[示例: 該程序接受一個可選的命令行參數,如果該參數為目錄路徑名,則對該目錄的內容進行遍歷。對於每個目錄項,輸出名字,如果某項為常 規文件則輸出文件的大小。

#include <iostream>
#include <filesystem>

using std::tr2::sys;
using std::cout;

int main(int argc, char* argv[])
{
std::string p(argc <= 1 ? "." : argv[1]);

if (is_directory(p))
{
for (directory_iterator itr(p); itr!=directory_iterator(); ++itr)
{
cout << itr->path().leaf() << ' '; // 只顯示文件名
if (is_regular(itr->status())) cout << " [" << file_size(itr->path()) << ']';
cout << '\n';
}
}
else cout << (exists(p) : "Found: " : "Not found: ") << p << '\n';

return 0;
}

-- 示例完]

目錄的遍歷不會產生當前目錄(dot)和父目錄(dot dot) 的目錄項。

一個 basic_directory_iterator& nbsp;持續遞增及提領所得到的目錄項的順序未指定。

[注: 執行目錄遍歷的程序可能想要測試從目錄迭代器提領所得的路徑是否真的存在。它可能是一個指向某個並不存在的文件的符號鏈接。對目錄樹進行遞歸遍歷並進行刪 除或改名操作的程序則可能希望避免進入符號鏈接。

如果在一個目錄的 basic_directory_iterator 構造完成後,才在目錄中刪除或加入一個文件,則後續的迭代器遞增過程中是否會得到指向被刪或被加入項的迭代器,是未指定的。參見 POSIX readdir_r(). --注完]

basic_directory_iterator 構造函數

basic_directory_iterator();

作用: 構造 end 迭代器。

explicit basic_directory_iterator(const Path& dp);

作用: 構造一個迭代器,表示由 dp 所解析得到的目錄中的第一項,否則為 end 迭代器。

[注: 要遍歷當前目錄,要寫 directory_iterator(".") 而不是 directory_iterator(""). -- 注完]

basic_directory_iterator(const Path& dp, error_code& ec );

作用: 構造一個迭代器,表示由 dp 所解析得到的目錄中的第一項,否則為 end 迭代器。如果在得到結果時發生錯誤,則所得迭代器為 end 迭代器且 ec 被設置為操作系統所報告的錯誤代碼,否則為 0.

類 模板 basic_recursive_directory_iterator

  namespace boost
{
namespace filesystem
{
template <class Path>
class basic_recursive_directory_iterator :
public iterator<input_iterator_tag, basic_directory_entry<Path> >
{
public:
typedef Path path_type;

// constructors
basic_recursive_directory_iterator();
explicit basic_recursive_directory_iterator(const Path& dp);
basic_recursive_directory_iterator(const basic_recursive_directory_iterator& brdi);
basic_recursive_directory_iterator& operator=(const basic_recursive_directory_iterator& brdi);
~basic_recursive_directory_iterator();

// observers
int level() const;

// modifiers
void pop();
void no_push();

// other members as required by
// C++ Std, 24.1.1 Input iterators [lib.input.iterators]

private:
int m_level; // for exposition only
};

} // namespace filesystem
} // namespace boost

basic_recursive_directory_iterator 的行為與 basic_directory_iterator 相同,除了特別說明。

[注: no_push() 的一個用法是防止遞歸進入符號鏈接的目錄。為防止某些操作系統上的循環訪問,這是必須的。--注完]

類 file_status

  namespace boost
{
namespace filesystem
{
class file_status
{
public:
explicit file_status( file_type v = status_unknown );

file_type type() const;
void type( file_type v );
};
} // namespace filesystem
} // namespace boost

file_status 對像保存了關於一個文件的狀態的信息。所保存的信息的內部形式未指定。

[注: 未來該類可能會被擴展,以保存更多的信息。--注完]

成員

explicit file_status( file_type v = status_unknown );

作用: 保存 v.

file_type type() const;

返回: 所保存的 file_type.

void type( file_type v );

作用: 保存 v, 替換原先保存的值。

非成員操作函數

狀態函數

template <class Path> file_status status(const Path& p, error_code& ec);
template <class Path> file_status symlink_status(const Path& p, error_code& ec);

返回:

對於 status, 確定 p 的屬性就像 POSIX stat(), 而對於 symlink_status 確定的屬性則像 POSIX lstat().

[注: 對於符號鏈接,stat() 會用符號鏈接的內容繼續進行路徑名解析,而 lstat() 則不會。-- 注完]

如果在屬性確定過程中,操作系統報告了錯誤,則:

否則:

[注: directory_file 表示在這個文件上可以使用 basic_directory_iterator,而 regular_file 則表示可以使用適當的 <fstream> 操作,假如沒有硬件、權限、訪問和競爭條件的錯誤。對於 regular_file, 反之則不一定為真;不是 regular_file 並不一定就表示 <fstream> 操作不能用於目錄。-- 注完]

template <class Path> file_status status(const Path& p);

作用: system_error_code ec;
              file_status stat(status(p, ec));

拋出: basic_filesystem_error<Path> 如果 ec != 0

返回: stat

template <class Path> file_status symlink_status(const Path& p);

作用: system_error_code ec;
              file_status stat(symlink_status(p, ec));

拋出: basic_filesystem_error<Path> 如果 ec != 0

返回: stat

謂詞函數

bool status_known(file_status s);

返回: s.type() != status_unknown

bool exists(file_status s);

返回: status_known(s) && s.type() != file_not_found

template <class Path> bool exists(const Path& p);

返回: exists( status(p) )

bool is_regular(file_status s);

返回: s.type() == regular_file

template <class Path> bool is_regular(const Path& p);

返回: is_regular( status(p) )

bool is_directory(file_status s);

返回: s.type() == directory_file

template <class Path> bool is_directory(const Path& p);

返回: is_directory( status(p) )

bool is_symlink(file_status s);

返回: s.type() == symlink_file

template <class Path> bool is_symlink(const Path& p);

返回: is_symlink( symlink_status(p) )

bool is_other(file_status s);

返回: return exists(s) && !is_regular(s) && !is_directory(s) && !is_symlink(s)

[注: is_other() 的規格保持不變,即使以後會加入 is_xxx() 函數。-- 注完]

template <class Path> bool is_other(const Path& p);

返回: is_other( status(p) )

template <class Path> bool is_empty(const Path& p);

作用: 確定 file_status s, 如 status(p).

拋出: basic_filesystem_error<Path> 如果 !exist(s) || is_other(s).

返回: is_directory(s)
         ? basic_directory_iterator<Path>(p) == basic_directory_iterator<Path>()
         : file_size(p) == 0;

template <class Path1, class Path2> bool equivalent(const Path1& p1, const Path2& p2);

要求: Path1::external_string_type Path2::external_string_type 為相同類型。

作用: 確定 file_status s1s2, 就如 status(p1) 和  status(p2).

拋出: basic_filesystem_error<Path1> 如 果 (!exists(s1) && !exists(s2)) || (is_other(s1) && is_other(s2)).

返回: true, 如果 sf1 == sf2p1p2 解析為同一個文件系統實體,否則返回 false.

兩個路徑被認為是解析為同一個文件系統實體,如果這兩個候選實體位於同一設備的同一位置。這就像 POSIX stat 結構的值所確定的那樣,對兩個路徑調用 stat() 所得到的值,具有相等的 st_dev 值和相等的 st_ino 值。

[注: POSIX 要求"st_dev 在一個LAN中必須是唯一的"。舊的 POSIX 實現可能還會檢查 st_sizest_mtime 值是否相等。Windows 實現可能用 GetFileInformationByHandle() 代替 stat(), 並認為"同一文件"是指 dwVolumeSerialNumber, nFileIndexHigh, nFileIndexLow, nFileSizeHigh, nFileSizeLow, ftLastWriteTime.dwLowDateTime, 和 ftLastWriteTime.dwHighDateTime 值的相等。-- 注完]

屬性函數

[注: 可提供的屬性函數數量是嚴格受限的,因為只有少量文件系統屬性是可移植的。即使提供了這些函數,在某些文件系統上也不可能實現。--注 完]

template <class Path> const Path& initial_path();

返回: 進入 main() 時的 current_path().

[注: 該語義將一個危險的全局變量變為一個安全的全局常量。--注完]

[注: 完整的實現需要運行期庫的支持。不能提供運行期庫支持的實現被建議保存第一次調用 initial_path() 時所得的 current_path(), 並在後續調用時返回該值。使用 initial_path() 的程序建議在進入 main() 後立即調用它,這樣在這些實現中才可以正確工作。-- 注完]

template <class Path> Path current_path();

返回: 當前路徑,如 POSIX getcwd().

後置條件: current_path().is_complete()

[注: 許多操作系統返回的當前路徑都是一個危險的全局變量。它可能會被某個第三方庫或系統庫的函數所修改,或者被其它線程修改。雖然危險,但是該函數在處理其它 庫函數時非常有用。作為一個安全的選擇,請見 initial_path(). 選擇 current_path() 這個名字,是為了強調返回的是一個完整的路徑,而不是單個目錄名。-- 注完]

template <class Path> void current_path(const Path& p);

後置條件: equivalent( p, current_path() );

template <class Path> uintmax_t file_size(const Path& p);

返回:p 所解析得到的文件的字節大小,類似於由 POSIX stat() 所得到的 POSIX stat 結構的成員 st_size 中所確定的。

template <class Path> space_info space(const Path& p);

返 回: 一個 space_info 對象。該 space_info 對象的值按以下方法確定,用 POSIX statvfs() 得到一個 POSIX 構造 statvfs, 然後以用其 f_frsize 成員與 f_blocks, f_bfree, 和 f_bavail 成員相乘,將結果分別賦值給 capacity, free, 和 available 成員。無法確定值的成員將被設為 -1.

template <class Path> std::time_t last_write_time(const Path& p);

返回: p 的最後修改時間,即通過 POSIX stat() 獲得的 POSIX stat 結構的成員 st_mtime 的值。

template <class Path> void last_write_time(const Path& p, const std::time_t new_time);

作用:p 所解析得到的文件的最後修改時間設置為 new_time, 就像 POSIX stat() 後跟 POSIX utime().

[注: 後置條件 last_write_time(p) == new_time 未被指定,因為對於多數文件系統,由於時間機制的粒度較粗而未能保證該條件。-- 注完]

其它操作函數

template <class Path> bool create_directory(const Path& dp);

作用: 嘗試創建一個由 dp 解析得到的目錄,如 POSIX mkdir(), 以 S_IRWXU|S_IRWXG|S_IRWXO 為第二參數。

拋出: basic_filesystem_error<Path> 如果上述作用因除目錄已存在以外的原因而失敗。

返回: True 如果創建了新目錄,否則返回 false.

後置條件: is_directory(dp)

template <class Path1, class Path2>
error_code create_hard_link(const Path1& to_p, const Path2& from_p, error_code& ec);

要求: Path1::external_string_type Path2::external_string_type 為相同類型。

作用: 建立後置條件,如 POSIX link().

返回: 如果後置條件不能建立,返回一個表示失敗原因的系統錯誤代碼,否則返回 0.

後置條件:

[注: 有些操作系統不支持硬鏈接或只對常規文件支持硬鏈接。有些操作系統則限制每個文件的鏈接數量。有些文件系統不支持硬鏈接 - 如用於軟盤、存儲卡和閃存盤的 FAT 系統。因此如果代碼的移植性是關鍵,則應避免硬鏈接。 -- 注完]

template <class Path1, class Path2>
void create_hard_link(const Path1& to_p, const Path2& from_p);

要求: Path1::external_string_type Path2::external_string_type 為相同類型。

作用:system_error_code ec( create_hard_link( to_p, from_p ) );

拋 出: basic_filesystem_error<Path1, Path2> 如果 ec 不為零。

template <class Path1, class Path2>
error_code create_symlink(const Path1& to_p, const Path2& from_p, error_code& ec);

要求: Path1::external_string_type Path2::external_string_type 為相同類型。

作用: 建立後置條件,如 POSIX symlink().

返回: 如果後置條件不能建立,則返回表示失敗原因的系統錯誤代碼,否則返回 0.

後 置條件: from_p 解析為一個符號鏈接文件,包含一個對 to_p 的未指定表示。

[注: 有些操作系統不支持符號鏈接或只對常規文件支持。因此如果代碼的可移植性是關鍵,則應避免符號鏈接。-- 注完]

template <class Path1, class Path2>
void create_symlink(const Path1& to_p, const Path2& from_p);

要求: Path1::external_string_type Path2::external_string_type 為相同類型。

作用:system_error_code ec( create_symlink( to_p, from_p ) );

拋 出: basic_filesystem_error<Path1, Path2> 如果 ec 不為零。

template <class Path> void remove(const Path& p, system::error_code & ec = singular );

作用:  刪除文件 p, 如 POSIX remove(). 如果底層實現沒有錯誤報告或如果 status(p).type() == file_not_found, 則:

否則,

後置條件: !exists(p)

拋出: 參見 作用

[注: 對於符號鏈接,其本身被刪除,而不是其所解析的文件被刪除。-- 注完]

template <class Path> unsigned long remove_all(const Path& p);

作用: 遞歸刪除 p 中的內容如果它存在,則刪除 p 文件本身,如 POSIX remove().

返回: 刪除文件的數量。

後置條件: !exists(p)

[注: 對於符號鏈接,其本身被刪除,而不是其所解析的文件被刪除。-- 注完]

template <class Path1, class Path2> void rename(const Path1& from_p, const Path2& to_p);

要求: Path1::external_string_type Path2::external_string_type 為相同類型。

作用:from_p 改名為 to_p, 如 POSIX rename().

後置條件: !exists(from_p) && exists(to_p), 且原來名為 from_p 的文件的內容和屬性不變。

[注: 如果 from_pto_p 為同一文件,則無操作。否則,如果 to_p 為已有文件,則被刪除。對於符號鏈接,其本身被改名,而不是其所指文件被改名。-- 注完]

template <class Path1, class Path2> void copy_file(const Path1& from_fp, const Path2& to_fp);

要求: Path1::external_string_type Path2::external_string_type 為相同類型。

作用: from_fp 所代表文件的內容和屬性被複製至 to_fp 所代表的文件。

拋出: basic_filesystem_error<Path> 如果 from_fp.empty() || to_fp.empty() ||!exists(from_fp) || !is_regular(from_fp) || exists(to_fp)

template <class Path> Path complete(const Path& p, const Path& base=initial_path<Path>());

作用:pbase 組合一個完整的路徑,使用以下規則:

  p.has_root_directory() !p.has_root_directory()
p.has_root_name() p 前提條件不滿足
!p.has_root_name() base.root_name()
/ p
base / p

返回: 組成的路徑。

後置條件: 對於返回的路徑 rp, rp.is_complete() 為 true.

拋出: 如果 !(base.is_complete() && (p.is_complete() || !p.has_root_name()))

[: 如果需要可移植的行為,請使用 complete(). 如果需要與操作系統相關的行為,則使用 system_complete().

如果要處理程序內部創建的路徑,則應使用可移植行為,特別是如果程序要在所有操作系統上表現出相同的行為。

如果要處理由用戶輸入的路徑,或向用戶輸出,或用戶期望的類似行為,則應使用與操作系統相關的行為-- 注完]

template <class Path> Path system_complete(const Path& p);

作用:p 組成一個完整路徑,使用與操作系統解析一個傳給標準庫 open 函數的路徑的相同規則。

返回: 組成的路徑。

後置條件: 對於返回的路徑 rp, rp.is_complete() 為 true.

拋出: 如果 p.empty().

[注: 對於 POSIX, system_complete(p) 具有與 complete(p, current_path()) 相同的語義。

對於 Windows, 如果 p.is_complete() || !p.has_root_name()pbase 具有相同的 root_name(),則 system_complete(p) 具有與 complete(ph, current_path()) 相同的語義。否則類似於 complete(p, kinky), 其中 kinkyp.root_name() 驅動器的當前目錄。它是該驅動器最後一次被設置的當前目錄,因此可能是命 令處理器所運行的上一個程序所遺留下來的!雖然這些語義常常被用到,但也是非常容易出錯的。

有關用法的建議,請見 complete() 註解-- 注完]

便利函數

template <class Path> bool create_directories(const Path & p);

要求: p.empty() ||
對於所有 px: px == p || is_parent(px, p): is_directory(px) || !exists( px )

返回: 達成後置條件之前的 !exists(p) 值。

後置條件: is_directory(p)

拋出:  basic_filesystem_error<Path> 如果 exists(p) && !is_directory(p)

不贊成使用的便利函數

以下函數已被 basic_path 的成員函數 extension(), stem(), 及 replace_extension() 所替代。

template <class Path> typename Path::string_type extension(const Path & p);

返回: 如果 p.leaf() 包含一個 dot, 則返回 p.leaf() 的子串,從最右邊的 dot 開始,以字符串的結尾結束。否則,返回一個空字符串。

[注: 返回值中包含 dot, 所以可以區分無擴展名和空擴展名的情況。

允許但不要求具體實現對於會為擴展名增加額外元素的文件系統定義額外的行為,如交替數據流或分區數據集的名字。-- 注完]

template <class Path> typename Path::string_type basename(const Path & p);

返回: 如果 p.leaf() 包含一個 dot, 則返回 p.leaf() 的子串,從開頭開始,以最後的 dot 結束(不包含 dot)。否 則返回 p.leaf().

template <class Path>
Path change_extension(const Path & p, const typename Path::string_type & new_extension);

後置條件: basename(return_value) == basename(p) && extension(return_value) == new_extension

[注: 它跟隨 extension() 的語義,即 new_extension 應包含 dot 以得到合理的結果。-- 注完]


對頭文件 <fstream> 的增加

以 下新增的規格是經過仔細考慮,以避免破壞在常用操作環境,如 POSIX, Windows, 和 OpenVMS 中的已有代碼。有關避免在其它環境中破壞已有代碼,請參見 <fstream> 實現的建議,尤其是在那些允許斜槓號出現在 文件名中的操作系統。

[注: 來自 對實現的要求 中的"do-the-right-thing" 規則被應用於頭文件 <fstream>.

以 下給出的重載是新增的,而不是替換已有函數。這樣保護了那些依賴於到 const char* 的自動轉換的已有代碼(可能使用了自已的路徑類)。-- 注完]

在 27.8.1.1 Class template basic_filebuf [lib.filebuf] 概要的第1段,增加函數:

template <class Path> basic_filebuf<charT,traits>* open(const Path& p, ios_base::openmode mode);

在 27.8.1.3 Member functions [lib.filebuf.members], 將上述增加到第2段的簽名中,並替換句子:

It then opens a file, if possible, whose name is the NTBS s (「as if」 by calling std::fopen(s ,modstr )).

為:

It then opens, if possible, the file that p or path(s) resolves to, 「as if」 by calling std::fopen() with a second argument of modstr.

在 27.8.1.5 Class template basic_ifstream [lib.ifstream] 概要的第1段,增加函數:

template <class Path> explicit basic_ifstream(const Path& p, ios_base::openmode mode = ios_base::in);
template <class Path> void open(const Path& p, ios_base::openmode mode = ios_base::in);

在 27.8.1.6 basic_ifstream constructors [lib.ifstream.cons] 中 增加上述構造函數到第2段的簽名中,並替換

rdbuf()->open(s, mode | ios_base::in)

rdbuf()->open(path(s), mode | ios_base::in) or rdbuf()->open(p, mode | ios_base::in) as appropriate

在 27.8.1.7 Member functions [lib.ifstream.members] 中增加上述 open 函數到第3段的簽名中,並替換

rdbuf()->open(s, mode | ios_base::in)

rdbuf()->open(path(s), mode | ios_base::in) or rdbuf()->open(p, mode | ios_base::in) as appropriate

在 27.8.1.8 Class template basic_ofstream [lib.ofstream] 概要的第1段,增加函數:

template <class Path> explicit basic_ofstream(const Path& p, ios_base::openmode mode = ios_base::out);
template <class Path> void open(const Path& p, ios_base::openmode mode = ios_base::out);

在 27.8.1.9 basic_ofstream constructors [lib.ofstream.cons] 中 增加上述構造函數到第2段的簽名中,並替換

rdbuf()->open(s, mode | ios_base::out)

rdbuf()->open(path(s), mode | ios_base::out) or rdbuf()->open(p, mode | ios_base::out) as appropriate

在 27.8.1.10 Member functions [lib.ofstream.members] 中增加上述 open 函數到第3段的簽名中,並替換

rdbuf()->open(s, mode | ios_base::out)

rdbuf()->open(path(s), mode | ios_base::out) or rdbuf()->open(p, mode | ios_base::out) as appropriate

在 27.8.1.11 Class template basic_fstream [lib.fstream] 概要第1段,增加函數:

template <class Path> explicit basic_fstream(const Path& p, ios_base::openmode mode = ios_base::in|ios_base::out);
template <class Path> void open(const Path& p, ios_base::openmode mode = ios_base::in|ios_base::out);

在 27.8.1.12 basic_fstream constructors [lib.fstream.cons] 中 增加上述構造函數到第2段的簽名中,並替換

rdbuf()->open(s, mode)

rdbuf()->open(path(s), mode) or rdbuf()->open(p, mode) as appropriate

在 27.8.1.13 Member functions [lib.fstream.members] 中增加上述 open 函數到第3段的簽名中,並替換

rdbuf()->open(s, mode)

rdbuf()->open(path(s), mode) or rdbuf()->open(p, mode) as appropriate

建 議文本結束。

路徑分解表

該表由以 Boost 實現編譯的程序生成。

有底色的項表示 POSIXWindows 實現會產生不同結果。上方的值為 POSIX 結果而下方的值為 Windows 結果。
 

構造函數參數 遍歷所找到的元素 string() file_
string()
root_
path()
.string()
root_
name()
root_
directory()
relative_
path()
.string()
parent_
path()
.string()
filename()
"" "" "" "" "" "" "" "" "" ""
"." "." "." "." "" "" "" "." "" "."
".." ".." ".." ".." "" "" "" ".." "" ".."
"foo" "foo" "foo" "foo" "" "" "" "foo" "" "foo"
"/" "/" "/" "/"
"\"
"/" "" "/" "" "" "/"
"/foo" "/","foo" "/foo" "/foo"
"\foo"
"/" "" "/" "foo" "/" "foo"
"foo/" "foo","." "foo/" "foo/"
"foo\"
"" "" "" "foo/" "foo" "."
"/foo/" "/","foo","." "/foo/" "/foo/"
"\foo\"
"/" "" "/" "foo/" "/foo" "."
"foo/bar" "foo","bar" "foo/bar" "foo/bar"
"foo\bar"
"" "" "" "foo/bar" "foo" "bar"
"/foo/bar" "/","foo","bar" "/foo/bar" "/foo/bar"
"\foo\bar"
"/" "" "/" "foo/bar" "/foo" "bar"
"///foo///" "/","foo","." "///foo///" "///foo///"
"\foo\\\"
"/" "" "/" "foo///" "///foo" "."
"///foo///bar" "/","foo","bar" "///foo///bar" "///foo///bar"
"\foo\\\bar"
"/" "" "/" "foo///bar" "///foo" "bar"
"/." "/","." "/." "/."
"\."
"/" "" "/" "." "/" "."
"./" ".","." "./" "./"
".\"
"" "" "" "./" "." "."
"/.." "/",".." "/.." "/.."
"\.."
"/" "" "/" ".." "/" ".."
"../" "..","." "../" "../"
"..\"
"" "" "" "../" ".." "."
"foo/." "foo","." "foo/." "foo/."
"foo\."
"" "" "" "foo/." "foo" "."
"foo/.." "foo",".." "foo/.." "foo/.."
"foo\.."
"" "" "" "foo/.." "foo" ".."
"foo/./" "foo",".","." "foo/./" "foo/./"
"foo\.\"
"" "" "" "foo/./" "foo/." "."
"foo/./bar" "foo",".","bar" "foo/./bar" "foo/./bar"
"foo\.\bar"
"" "" "" "foo/./bar" "foo/." "bar"
"foo/.." "foo",".." "foo/.." "foo/.."
"foo\.."
"" "" "" "foo/.." "foo" ".."
"foo/../" "foo","..","." "foo/../" "foo/../"
"foo\..\"
"" "" "" "foo/../" "foo/.." "."
"foo/../bar" "foo","..","bar" "foo/../bar" "foo/../bar"
"foo\..\bar"
"" "" "" "foo/../bar" "foo/.." "bar"
"c:" "c:" "c:" "c:" ""
"c:"
""
"c:"
"" "c:"
""
"" "c:"
"c:/" "c:","."
"c:","/"
"c:/" "c:/"
"c:\"
""
"c:/"
""
"c:"
""
"/"
"c:/"
""
"c:" "."
"/"
"c:foo" "c:foo"
"c:","foo"
"c:foo" "c:foo" ""
"c:"
""
"c:"
"" "c:foo"
"foo"
""
"c:"
"c:foo"
"foo"
"c:/foo" "c:","foo"
"c:","/","foo"
"c:/foo" "c:/foo"
"c:\foo"
""
"c:/"
""
"c:"
""
"/"
"c:/foo"
"foo"
"c:"
"c:/"
"foo"
"c:foo/" "c:foo","."
"c:","foo","."
"c:foo/" "c:foo/"
"c:foo\"
""
"c:"
""
"c:"
"" "c:foo/"
"foo/"
"c:foo" "."
"c:/foo/" "c:","foo","."
"c:","/","foo","."
"c:/foo/" "c:/foo/"
"c:\foo\"
""
"c:/"
""
"c:"
""
"/"
"c:/foo/"
"foo/"
"c:/foo" "."
"c:/foo/bar" "c:","foo","bar"
"c:","/","foo","bar"
"c:/foo/bar" "c:/foo/bar"
"c:\foo\bar"
""
"c:/"
""
"c:"
""
"/"
"c:/foo/bar"
"foo/bar"
"c:/foo" "bar"
"prn:" "prn:" "prn:" "prn:" ""
"prn:"
""
"prn:"
"" "prn:"
""
"" "prn:"
"c:\" "c:\"
"c:","/"
"c:\"
"c:/"
"c:\" ""
"c:/"
""
"c:"
""
"/"
"c:\"
""
""
"c:"
"c:\"
"/"
"c:foo" "c:foo"
"c:","foo"
"c:foo" "c:foo" ""
"c:"
""
"c:"
"" "c:foo"
"foo"
""
"c:"
"c:foo"
"foo"
"c:\foo" "c:\foo"
"c:","/","foo"
"c:\foo"
"c:/foo"
"c:\foo" ""
"c:/"
""
"c:"
""
"/"
"c:\foo"
"foo"
""
"c:/"
"c:\foo"
"foo"
"c:foo\" "c:foo\"
"c:","foo","."
"c:foo\"
"c:foo/"
"c:foo\" ""
"c:"
""
"c:"
"" "c:foo\"
"foo/"
""
"c:foo"
"c:foo\"
"."
"c:\foo\" "c:\foo\"
"c:","/","foo","."
"c:\foo\"
"c:/foo/"
"c:\foo\" ""
"c:/"
""
"c:"
""
"/"
"c:\foo\"
"foo/"
""
"c:/foo"
"c:\foo\"
"."
"c:\foo/" "c:\foo","."
"c:","/","foo","."
"c:\foo/"
"c:/foo/"
"c:\foo/"
"c:\foo\"
""
"c:/"
""
"c:"
""
"/"
"c:\foo/"
"foo/"
"c:\foo"
"c:/foo"
"."
"c:/foo\bar" "c:","foo\bar"
"c:","/","foo","bar"
"c:/foo\bar"
"c:/foo/bar"
"c:/foo\bar"
"c:\foo\bar"
""
"c:/"
""
"c:"
""
"/"
"c:/foo\bar"
"foo/bar"
"c:"
"c:/foo"
"foo\bar"
"bar"

<fstream> 實現的建議

對 於接受 const char* 參數的函數的語義的改動會破壞已有代碼,但是僅會發生在那些不支持 隱 式接受原生格式路徑名 或允許斜槓號用於文件名的操作系統中。因此在 POSIX, Windows,OpenVMS 上,如果實現遵守推薦行為就不會有問題。

對 於多數 Filesystem 庫,並沒有已有代碼,所以在文件名中使用斜槓號的問題並不會發生。新代碼只須使用帶有 path_format_t 參數的 basic_path 構造函數。為保護那些在文件名中使用了斜槓號的已有 fstream 代碼,實現可能要提供一個機制,如某個宏,來控制選用舊的行為。

TR 的前頁已要求具體實現要提供一個機制,如某個宏,來控制頭文件選用舊的行為(為了保護已有代碼)或新的行為(用於新代碼以及從其它系統移植來的代碼)。因 為 Filesystem 庫的其餘部分的使用與 <fstream> 新增內容無關,所以建議受到影響的實現可以與其它TR特性分開,單獨禁用 <fstream> 新增內容。

另 一種被拒絕的選擇是,在名字空間 filesystem 中提供新的 fstream 類,它們派生自當前的類,覆蓋各個構造函數和 open 函數,接受路徑名參數,並提供其它重載。在 Lillehammer LWG members 中說明了這一方法的缺點,感覺上它的開銷高於所獲得的好處。

鳴謝

This Filesystem Library is dedicated to my wife, Sonda, who provided the support necessary to see both a trial implementation and the proposal itself through to completion. She gave me the strength to continue after a difficult year of cancer treatment in the middle of it all.

Many people contributed technical comments, ideas, and suggestions to the Boost Filesystem Library. See http://www.boost.org/libs/filesystem/doc/index.htm#Acknowledgements.

Dietmar Kuhl contributed the original Boost Filesystem Library directory_iterator design. Peter Dimov, Walter Landry, Rob Stewart, and Thomas Witt were particularly helpful in refining the library.

The create_directories, extension, basename, and replace_extension functions were developed by Vladimir Prus.

Howard Hinnant and John Maddock reviewed a draft of the proposal, and identified a number of mistakes or weaknesses, resulting in a more polished final document.

參考

[ISO-POSIX] ISO/IEC 9945:2003, IEEE Std 1003.1-2001, and The Open Group Base Specifications, Issue 6. Also known as The Single UnixR Specification, Version 3. Available from each of the organizations involved in its creation. For example, read online or download from www.unix.org/single_unix_specification/. The ISO JTC1/SC22/WG15 - POSIX homepage is www.open-std.org/jtc1/sc22/WG15/
[Abrahams] Dave Abrahams, Error and Exception Handling, www.boost.org/more/error_handling.html

c Copyright Beman Dawes, 2002, 2006, 2007

Distributed under the Boost Software License, Version 1.0. See www.boost.org/LICENSE_1_0.txt

Revised 13 October 2008