boost Filesystem 库

source : http://qa.alibaba.com/docs/boost_doc/libs/filesystem/doc/reference.html#Class-template-basic_recursive_directory_iterator


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对象。-- 注完]

这两个重载没有在正式文本中给出,是因为:

  • 可能会有更好的方法达到这一效果,如通过核心语言实现对 Concepts 的支持。
  • 实现可能会选用其它技术,以便用于那些不支持 enable_if 的旧编译器。
  • 清楚说明这些重载会使得文本更长,更难以阅读,而没有增加任何好处。
  • 对于 char16_t 和 char32_t 可能需要更多的重载(或者规定它们不允许调用),每一个都要讲清楚就更麻烦了。

本文中的函数的实现可以调用由操作系统系统提供的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);

      BOOST_SCOPED_ENUM_START(copy_option)
        { fail_if_exists, overwrite_if_exists };
      BOOST_SCOPED_ENUM_END

      template <class Path1, class Path2>
        void copy_file(const Path1& from_fp, const Path2& to_fp,
          BOOST_SCOPED_ENUM(copy_option) option=copy_option::fail_if_exists);

      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 的私有成员 boolm_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_localecodecvt facet 转换为 external_string_type.
Traits::to_internal(p, xs )xs, 被 m_localecodecvt 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对象解析为文件层次中的一个特定文件。路径名被合适地转换为操作系统所要求的字符串类型、格式和编码,按 POSIXPathnameResolution 机制进行解析。结果路径名的编码由 Traits::to_external转换函数决定。

[注:并不保证保存在 basic_path对象中的路径对于特定的操作系统或文件系统是有效的。-- 注完]

本文中有些函数返回的 basic_path对象部分或全部由得自操作系统的路径名组成。这些路径名被从由操作系统提供的真实格式和字符串类型进行合适的转换。结果路径的编码由 Traits::to_internal转换函数决定。

那些返回 "const string_type" 或 "constexternal_string_type" 的成员函数,允许被实现为分别返回 "conststring_type&" 或 "constexternal_string_type&"。

[注:这允许实现避免不必要的复制。指定以常量值返回可以确保在转换为以引用返回的实现时不会破坏已有程序。-- 注完]

路径名格式

有两种格式的字符串或字符序列参数来表示一个路径:

  • 可移植的路径名格式,在 路径名语法中描述,由 POSIX Filename,Pathname Pathname Resolution 定义。

    [注:POSIX格式是可移植格式的基础,因为它已经是一个ISO标准了,它也是广泛采用的URL格式,是类UNIX和类Windows操作系统的原生格式或其子集,为广大程序员所熟悉。

    单靠使用可移植格式并不能保证可移植性;文件名也必须是可移植的。请见 文件名转换。每个操作系统都有它自己的规则。使用可移植格式并不能改变这些规则。 -- 注完]

  • 由操作系统定义的原生路径名格式。

    [注:如果操作系统只支持POSIX路径名格式,则可移植格式和原生格式就是一样的。

    确定用户所提供的路径作为原生格式,是一种常见的需要,并且确保了最大的可移植性,虽然这并不是严格需要的,除了在那些原生格式未被公认的系统上。

    使用硬编码原生格式的程序很可能是不可移植的。-- end note]

所有 basic_path的描述路径的字符串或字符序列参数都接受可移植路径名格式,也接受由原生格式转义序列前缀"//:"显式标识的原生格式。

[注:"//:"被选择作为转义序列,是因为在POSIX中"//"是由实现定义的,":"则是不允许用于Windows文件,而且在任何系统中如果想表示以":"开头的文件名,可以使用单个"/"。以上因素一起消除了这个转义序列与某个真实文件名发生冲突的可能。-- 注完]

如果在文字上可以区分开,实现最好可以直接接受原生的路径名格式。每个实现应该在文档中写明是否可以直接接受原生路径名格式。

[例如:

-- OpenVMS: "SYS1::DISK1:[JANE.TYLER.HARRY]"被视为带有系统名、驱动器名和三个目录文件名的原生路径名,而不是某个文件名的可移植路径名。

-- Windows: "c:\\jane\\tyler\\harry"被视为带有驱动器名、根目录和三个文件名的原生路径名,而不是某个文件名的可移植路径名。

-- 反例1:某个操作系统允许在文件名中使用"/",它使用"."作为目录分隔符。区分可移植格式和原生格式的字符串或字符序列是不可能的,如果没有其它可区分的语法。所以实现不接受原生格式的路径名,除非指定一个原生参数。

-- 反例2:某个操作系统允许在文件名中使用"/",它使用一些不常见的字符作为目录分隔符。这时实现不能接受不带有额外的原生参数的原生格式路径名,原生参数必须被用于在文件名中含有"/"的原生格式参数。

-- 举例完]

[注:鸭子规则duck-rule("如果某个东西看起来象鸭子,走起来象鸭子,叫进来象鸭子,那么它就是一只鸭子")消除了源自程序员错误和支持要求的格式混乱。--注完]

如果可以同时接受可移植格式和原生格式,则实现应该在文档中说明哪些字符或字符序列被用作区分可移植格式和原生格式。

[注:Windows实现被鼓励将":"和"\"定义为区分原生格式和可移植格式的字符。--注完]

路径名语法

可移植路径名格式的语法如下:

pathname:
           root-nameopt root-directoryoptrelative-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,PathnamePathnameResolution 定义的。该语法与 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;

返回: 所保存的路径,按照操作系统关于常规文件路径名的规则进行格式化,带 文件名转换

[注: 对于某些操作系统,包括 POSIXWindows, 常规文件和目录的路径名的原生格式是相同的,所以 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 对象的任何非常性成员函数的调用将使得引向该对象元素的所有迭代器均失效。

前向遍历的顺序如下:

  • root-name 元素,如果有的话。
  • root-directory 元素,如果有的话。
  • 每个相继的 filename 元素,如果有的话。
  • Dot, 如果尾部有一个或多个非根的"/"字符。

后向遍历的顺序与前向遍历相反。

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<classString, class Traits>. 这些参数的格式在 路径名格式 中描述。

参数类型重载

basic_path<String, Traits>& a,basic_path<String, Traits>& b
consttypename basic_path<String, Traits>::string_type&a, basic_path<String, Traits>& b
consttypename basic_path<String,Traits>::string_type::value_type* a, basic_path<String,Traits>& b
constbasic_path<String, Traits>& a, typenamebasic_path<String, Traits>::string_type& b
constbasic_path<String, Traits>& a, typenamebasic_path<String, Traits>::string_type::value_type* b

basic_path非成员操作符 表中,ab参数类型重载 表中给出的类型。如果 ab 的类型为 constbasic_path<String, Traits>&, 则 a'b' 分别为 ab. 否则 a'b' 分别表示从 ab 构造的有名或无名的 basic_path<String,Traits> 临时对象。

basic_path非成员操作符
表达式返回类型语义
a / bbasic_path<String,Traits>basic_path<String, Traits> tmp(a);
return a /=
b';
a < bboolreturnlexicographical_compare(a'.begin(), a'.end(), b'.begin(), b'.end());
a == bboolreturn !(a' < b')&& !(b' < a');
a != bboolreturn !(a' == b');
a > bboolreturn b' < a';
a <= bboolreturn !(b' < a');
a >= bboolreturn !(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 );

作用:  typenamePath::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秒钟。测试环境为:WindowsXP, 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从其构造的目录中持续读入元素,类似于调用 POSIXreaddir_r().当一个 basic_directory_iterator 被构造后,每一次调用 operator++,它读入并保存一个 basic_directory_entry<Path>值及其可能带有的相关状态值。operator++ 不保持等同性,即:i== j 并不意味着++i == ++j.

[注: 不保持等同性的后果是,目录迭代器只能被用于单次遍历的算法。--注完]

如果到达目录元素的末尾,迭代器将变为等同于 end 迭代器值。不带参数的构造函数 basic_directory_iterator()总是构造一个 end 迭代器对象,它是唯一一个用于结束条件的合法迭代器。一个 end 迭代器的 operator* 结果是未定义的。对于其它迭代器值,则返回一个 constbasic_directory_entry<Path>&. 一个 end迭代器的operator-> 结果也是未定义的。对于其它迭代器,则返回一个 constbasic_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(constPath& 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 相同,除了特别说明。

  • 一个迭代器被构造后,m_level 设为 0;
  • 递增一个迭代器时,如果 it->is_directory()为 true 且 no_push() 没有紧接着最后一个递增操作(或构造时)调用,则 m_level被递增,并进入该目录且递归遍历其内容。
  • 当一个迭代器到达其当前遍历的目录末尾时,或者 pop() 被调用时,m_level被递减,且后续将对父目录进行遍历,直至到达构造函数的参数所指定的目录。
  • level() 返回 m_level.
  • level(), pop(),和 no_push() 都要求该迭代器不是 end 迭代器。

[注: 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() 则不会。--注完]

如果在属性确定过程中,操作系统报告了错误,则:

  • 如果错误说明 p 不能被解析,象 POSIX 的错误代码ENOENT 或 ENOTDIR 那样,则设置 ec 为 0 并返回 file_status(not_found_flag).
  • 否则,设置 ec 为操作系统报告的错误代码并返回 file_status(status_unknown).
否则:
  • 如果属性显示是一个常规文件,如 POSIX S_ISREG(),则返回 file_status(regular_file).
  • 否则如果属性显示是一个目录,如 POSIX S_ISDIR(),则返回 file_status(directory_file).
  • 否则如果属性显示是一个符号链接,如 POSIX S_ISLNK(),则返回 file_status(symlink_file). [注:只能用于 symlink_status. --注完]
  • 否则如果属性显示是一个块设备文件,如 POSIX S_ISBLK(),则返回 file_status(block_file).
  • 否则如果属性显示是一个字符设备文件,如 POSIX S_ISCHR(),则返回 file_status(character_file).
  • 否则如果属性显示是一个 fifo 或管道文件,如 POSIX S_ISFIFO(),则返回 file_status(fifo_file).
  • 否则如果属性显示是一个 socket, 如 POSIX S_ISSOCK(),则返回 file_status(socket_file).
  • 否则返回 file_status(type_unknown).

[注: 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);

返回: returnexists(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_typePath2::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_typePath2::external_string_type 为相同类型。

作用: 建立后置条件,如 POSIX link().

返回:如果后置条件不能建立,返回一个表示失败原因的系统错误代码,否则返回 0.

后置条件:

  • exists(to_p)&& exists(from_p) && equivalent(to_p,from_p)
  •  to_p所解析的文件或目录的内容不变。

[注:有些操作系统不支持硬链接或只对常规文件支持硬链接。有些操作系统则限制每个文件的链接数量。有些文件系统不支持硬链接 -如用于软盘、存储卡和闪存盘的 FAT 系统。因此如果代码的移植性是关键,则应避免硬链接。 -- 注完]

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

要求: Path1::external_string_typePath2::external_string_type 为相同类型。

作用:system_error_codeec( 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_typePath2::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_typePath2::external_string_type 为相同类型。

作用:system_error_codeec( 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, 则:

  • 如果 ec != singular,则 ec.clear().

否则,

  • 如果 ec != singular,则设置 ec 以表示该错误。
  • 否则,抛出 basic_filesystem_error<Path>以表示该错误。如果 ec != singular,则 ec.clear()

后置条件: !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_typePath2::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,
                 BOOST_SCOPED_ENUM(copy_option) option=copy_option::fail_if_exists);

要求: Path1::external_string_typePath2::external_string_type 为相同类型。

作用: from_fp所代表文件的内容和属性被复制至 to_fp 所代表的文件。

抛出: basic_filesystem_error<Path> if from_fp.empty() || to_fp.empty() ||!exists(from_fp) || !is_regular_file(from_fp) || (option==copy_option::fail_if_exists && 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>.

以下给出的重载是新增的,而不是替换已有函数。这样保护了那些依赖于到 constchar*的自动转换的已有代码(可能使用了自已的路径类)。--注完]

在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段的签名中,并替换句子:

Itthen opens a file, if possible, whose name is the NTBS s (“as if” bycalling std::fopen(s ,modstr )).

为:

Itthen 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.5Class 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.6basic_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.7Member 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.8Class 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.9basic_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.10Member 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.11Class 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.12basic_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.13Member 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, whoprovided the support necessary to see both a trial implementation andthe proposal itself through to completion. She gave me the strength tocontinue after a difficult year of cancer treatment in the middle of itall.

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

Dietmar Kühl contributed the original Boost Filesystem Librarydirectory_iterator design. Peter Dimov, Walter Landry, Rob Stewart, andThomas Witt were particularly helpful in refining the library.

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

Howard Hinnant and John Maddock reviewed a draft of theproposal, and identified a number of mistakes or weaknesses, resultingin a more polished final document.

参考

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

© Copyright Beman Dawes, 2002, 2006, 2007

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

Revised 17 May 2009


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值