Boost.Filesystem 使用 以及文件时间

来源:互联网 发布:java权限系统设计 编辑:程序博客网 时间:2024/05/23 01:32

1 boost:

Boost.Filesystem 库为对路径、文件和目录进行查询和操作提供了可移植的工具,已经被C++标准委员会接纳包含到TR2中。

头文件

#include <boost/filesystem.hpp>


所有Boost.Filesystem库的内容都处于名空间boost::filesystem之内。

认识basic_path类

在Boost.Filesystem库里basic_path是最重要的类,它以系统无关的方式保存路径、文件名。象std::basic_string 一样,针对char和wchar_t,分别特化了path和wpath。

basic_path的构造函数:

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

输入参数是一个字符串(或字符迭代器),表示路径名,可以输入系统原生路径名或可移植路径名
原生路径名没啥好说的,比如C:/Windows; D:/abc/ttt.txt等
可移植路径名的定义和Unix的路径定义相同,以“/”作为路径分隔符。

basic_path成员函数:

成员函数作用template <class InputIterator>basic_path& append(InputIterator first, InputIterator last);将字符串 s 或字符序列 [first,last) 中的路径元素追加到保存的路径中。basic_path& remove_filename();去除路径中的文件名basic_path& replace_extension( const string_type & new_extension = "" );替换扩展名string_type string()得到可移植路径名string_type file_string()得到系统原生文件名string_type directory_string()得到系统原生路径名string_type root_name() const;得到根名string_type root_directory() const;得到根目录basic_path root_path() const;得到根路径:根名+根目录basic_path relative_path() const;得到相对路径string_type filename() const;得到文件名basic_path parent_path() const;得到父路径:根路径+相对路径string_type stem(const Path & p) const;得到不带扩展名的文件名string_type extension(const Path & p) const;得到扩展名bool empty() const;path未赋值bool is_complete() const;是否是完整路径bool has_root_path() const;
bool has_root_name() const;
bool has_root_directory() const;
bool has_relative_path() const;
bool has_filename() const;
bool has_branch_path() const;路经中是否包含指定的项

 

测试代码:

  1. #include "boost/filesystem.hpp"   // 包含所有需要的 Boost.Filesystem 声明
  2. #include <iostream>               // 使用 std::cout
  3. namespace fs = boost::filesystem;
  4. // 宏FSTEST:测试f的成员函数,输出成员函数名和结果
  5. #define FSTEST(x) std::cout << #x##": " << f.x << std::endl
  6. int main()
  7. {
  8.     fs::path f("//folder1//folder2//folder3//filename.ext");
  9.  
  10.     FSTEST(string());
  11.     FSTEST(file_string());
  12.     FSTEST(directory_string());
  13.     FSTEST(root_name());
  14.     FSTEST(root_directory());
  15.     FSTEST(root_path());
  16.     FSTEST(relative_path());
  17.     FSTEST(filename());
  18.     FSTEST(parent_path());
  19.     FSTEST(stem());
  20.     FSTEST(extension());
  21.  
  22.     FSTEST(replace_extension("new"));
  23.     char buf[]="hello";
  24.     FSTEST(append(buf, buf+sizeof(buf)));
  25.     FSTEST(remove_filename());
  26.  
  27.     return 0;
  28. }

 

输出:

string(): /folder1/folder2/folder3/filename.ext file_string(): /folder1/folder2/folder3/filename.ext directory_string(): /folder1/folder2/folder3/filename.ext root_name(): root_directory(): / root_path(): / relative_path(): folder1/folder2/folder3/filename.ext filename(): filename.ext parent_path(): /folder1/folder2/folder3 stem(): filename extension(): .ext replace_extension("new"): /folder1/folder2/folder3/filename.new append(buf, buf+sizeof(buf)): /folder1/folder2/folder3/filename.new/hello remove_filename(): /folder1/folder2/folder3/filename.new/

 

常用函数

函数名作用system_complete(path);返回完整路径(相对路径+当前路径)exists(path);文件是否存在is_directory(path);
is_directory(file_status);是否是路径is_regular_file(path);
is_regular_file(file_status);是否是普通文件is_symlink(path);
is_symlink(file_status);是否是一个链接文件file_status status(path);返回路径名对应的状态template <class Path> const Path& initial_path();得到程序运行时的系统当前路径template <class Path> Path current_path();得到系统当前路径template <class Path> void current_path(const Path& p);改变当前路径template <class Path> space_info space(const Path& p);得到指定路径下的空间信息,space_info 有capacity, free 和 available三个成员变量,分别表示容量,剩余空间和可用空间。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);修改最后修改时间template <class Path> bool create_directory(const Path& dp);建立路径template <class Path1, class Path2> void create_hard_link(const Path1& to_p, const Path2& from_p);
template <class Path1, class Path2> error_code create_hard_link(const Path1& to_p, 
const Path2& from_p, error_code& ec);建立硬链接template <class Path1, class Path2> void create_symlink(const Path1& to_p, const Path2& from_p);
template <class Path1, class Path2> error_code create_symlink(const Path1& to_p, const Path2& from_p, error_code& ec); 建立软链接template <class Path> void remove(const Path& p, system::error_code & ec = singular );删除文件template <class Path> unsigned long remove_all(const Path& p);递归删除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 complete(const Path& p, const Path& base=initial_path<Path>());以base以基,p作为相对路径,返回其完整路径template <class Path> bool create_directories(const Path & p);建立路径

 

路径迭代器

basic_directory_iterator

构造函数:

explicit basic_directory_iterator(const Path& dp); basic_directory_iterator();
basic_directory_iterator 从构造参数得到目录,每一次调用 operator++,它就查找并得到下一个文件名直到目录元素的末尾。不带参数的构造函数 basic_directory_iterator() 总是构造一个 end 迭代器对象,它是唯一一个用于结束条件的合法迭代器。

示例代码,得到指定目录下的所有文件名:

  1. void find_file( const fs::path & dir_path )
  2. {
  3.     if ( !fs::exists( dir_path ) ) return;
  4.     fs::directory_iterator end_itr; // 缺省构造生成一个结束迭代器
  5.     for ( fs::directory_iterator itr( dir_path );
  6.         itr != end_itr;
  7.         ++itr )
  8.     {
  9.         if ( fs::is_directory(itr->status()) )
  10.         {
  11.             find_file( itr->path() ); //递归查找
  12.         }
  13.         else
  14.         {
  15.             std::cout << *itr << std::endl;
  16.         }
  17.   }
  18. }

 

basic_recursive_directory_iterator

递归遍历目录的迭代器,它的构造参数与basic_directory_iterator相同,当调用 operator++时,如果当前值是一个目录,则进入下一级目录。
它有三个成员函数:

函数名作用int level() const;得到当前搜索深度void pop();调用pop()后,下一次递增就会直接返回上一级目录void no_push();调用no_push()后,即便下一个元素是目录类型也不进入


示例代码,得到指定目录下的所有文件名(和上例作用相同):

  1. void find_file2( const fs::path & dir_path )
  2. {
  3.     fs::recursive_directory_iterator end_itr; // 缺省构造生成一个结束迭代器
  4.     for ( fs::recursive_directory_iterator itr( dir_path );
  5.         itr != end_itr;
  6.         ++itr )
  7.     {
  8.         std::cout << itr.level() << *itr << std::endl;
  9.     }

//
Boost.Filesystem 库为对路径、文件和目录进行查询和操作提供了可移植的工具,已经被C++标准委员会接纳包含到TR2中。

编译

使用Boost.Filesystem 库之前要先编译它,请参考《Boost的编译》

头文件

#include <boost/filesystem.hpp>

所有Boost.Filesystem库的内容都处于名空间boost::filesystem之内。

认识basic_path类

在Boost.Filesystem库里basic_path是最重要的类,它以系统无关的方式保存路径、文件名。象std::basic_string 一样,针对char和wchar_t,分别特化了path和wpath。

basic_path的构造函数:
basic_path( const string_type & s ); basic_path( const value_type * s ); template <class InputIterator> basic_path(InputIterator s, InputIterator last);
输入参数是一个字符串(或字符迭代器),表示路径名,可以输入系统原生路径名或可移植路径名
原生路径名没啥好说的,比如C:\Windows; D:\abc\ttt.txt等
可移植路径名的定义和Unix的路径定义相同,以“/”作为路径分隔符。

basic_path成员函数:

成员函数作用template <class InputIterator>basic_path& append(InputIterator first, InputIterator last);将字符串 s 或字符序列 [first,last) 中的路径元素追加到保存的路径中。basic_path& remove_filename();去除路径中的文件名basic_path& replace_extension( const string_type & new_extension = "" );替换扩展名string_type string()得到可移植路径名string_type file_string()得到系统原生文件名string_type directory_string()得到系统原生路径名string_type root_name() const;得到根名string_type root_directory() const;得到根目录basic_path root_path() const;得到根路径:根名+根目录basic_path relative_path() const;得到相对路径string_type filename() const;得到文件名basic_path parent_path() const;得到父路径:根路径+相对路径string_type stem(const Path & p) const;得到不带扩展名的文件名string_type extension(const Path & p) const;得到扩展名bool empty() const;path未赋值bool is_complete() const;是否是完整路径bool has_root_path() const;
bool has_root_name() const;
bool has_root_directory() const;
bool has_relative_path() const;
bool has_filename() const;
bool has_branch_path() const;路经中是否包含指定的项

测试代码:

  1. #include "boost/filesystem.hpp"   // 包含所有需要的 Boost.Filesystem 声明
  2. #include <iostream>               // 使用 std::cout
  3. namespace fs = boost::filesystem;
  4. // 宏FSTEST:测试f的成员函数,输出成员函数名和结果
  5. #define FSTEST(x) std::cout << #x##": " << f.x << std::endl
  6. int main()
  7. {
  8.     fs::path f("\\folder1\\folder2\\folder3\\filename.ext");
  9.  
  10.     FSTEST(string());
  11.     FSTEST(file_string());
  12.     FSTEST(directory_string());
  13.     FSTEST(root_name());
  14.     FSTEST(root_directory());
  15.     FSTEST(root_path());
  16.     FSTEST(relative_path());
  17.     FSTEST(filename());
  18.     FSTEST(parent_path());
  19.     FSTEST(stem());
  20.     FSTEST(extension());
  21.  
  22.     FSTEST(replace_extension("new"));
  23.     char buf[]="hello";
  24.     FSTEST(append(buf, buf+sizeof(buf)));
  25.     FSTEST(remove_filename());
  26.  
  27.     return 0;
  28. }

输出:

string(): /folder1/folder2/folder3/filename.ext file_string(): \folder1\folder2\folder3\filename.ext directory_string(): \folder1\folder2\folder3\filename.ext root_name(): root_directory(): / root_path(): / relative_path(): folder1/folder2/folder3/filename.ext filename(): filename.ext parent_path(): /folder1/folder2/folder3 stem(): filename extension(): .ext replace_extension("new"): /folder1/folder2/folder3/filename.new append(buf, buf+sizeof(buf)): /folder1/folder2/folder3/filename.new/hello remove_filename(): /folder1/folder2/folder3/filename.new/

常用函数

函数名作用system_complete(path);返回完整路径(相对路径+当前路径)exists(path);文件是否存在is_directory(path);
is_directory(file_status);是否是路径is_regular_file(path);
is_regular_file(file_status);是否是普通文件is_symlink(path);
is_symlink(file_status);是否是一个链接文件file_status status(path);返回路径名对应的状态template <class Path> const Path& initial_path();得到程序运行时的系统当前路径template <class Path> Path current_path();得到系统当前路径template <class Path> void current_path(const Path& p);改变当前路径template <class Path> space_info space(const Path& p);得到指定路径下的空间信息,space_info 有capacity, free 和 available三个成员变量,分别表示容量,剩余空间和可用空间。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);修改最后修改时间template <class Path> bool create_directory(const Path& dp);建立路径template <class Path1, class Path2> void create_hard_link(const Path1& to_p, const Path2& from_p);
template <class Path1, class Path2> error_code create_hard_link(const Path1& to_p, 
const Path2& from_p, error_code& ec);建立硬链接template <class Path1, class Path2> void create_symlink(const Path1& to_p, const Path2& from_p);
template <class Path1, class Path2> error_code create_symlink(const Path1& to_p, const Path2& from_p, error_code& ec); 建立软链接template <class Path> void remove(const Path& p, system::error_code & ec = singular );删除文件template <class Path> unsigned long remove_all(const Path& p);递归删除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 complete(const Path& p, const Path& base=initial_path<Path>());以base以基,p作为相对路径,返回其完整路径template <class Path> bool create_directories(const Path & p);建立路径

路径迭代器

basic_directory_iterator

构造函数:
explicit basic_directory_iterator(const Path& dp); basic_directory_iterator();
basic_directory_iterator 从构造参数得到目录,每一次调用 operator++,它就查找并得到下一个文件名直到目录元素的末尾。不带参数的构造函数 basic_directory_iterator() 总是构造一个 end 迭代器对象,它是唯一一个用于结束条件的合法迭代器。

示例代码,得到指定目录下的所有文件名:
  1. void find_file( const fs::path & dir_path )
  2. {
  3.     if ( !fs::exists( dir_path ) ) return;
  4.     fs::directory_iterator end_itr; // 缺省构造生成一个结束迭代器
  5.     for ( fs::directory_iterator itr( dir_path );
  6.         itr != end_itr;
  7.         ++itr )
  8.     {
  9.         if ( fs::is_directory(itr->status()) )
  10.         {
  11.             find_file( itr->path() ); //递归查找
  12.         }
  13.         else
  14.         {
  15.             std::cout << *itr << std::endl;
  16.         }
  17.   }
  18. }

basic_recursive_directory_iterator

递归遍历目录的迭代器,它的构造参数与basic_directory_iterator相同,当调用 operator++时,如果当前值是一个目录,则进入下一级目录。
它有三个成员函数:函数名作用int level() const;得到当前搜索深度void pop();调用pop()后,下一次递增就会直接返回上一级目录void no_push();调用no_push()后,即便下一个元素是目录类型也不进入
示例代码,得到指定目录下的所有文件名(和上例作用相同):
  1. void find_file2( const fs::path & dir_path )
  2. {
  3.     fs::recursive_directory_iterator end_itr; // 缺省构造生成一个结束迭代器
  4.     for ( fs::recursive_directory_iterator itr( dir_path );
  5.         itr != end_itr;
  6.         ++itr )
  7.     {
  8.         std::cout << itr.level() << *itr << std::endl;
  9.     }

//

对于 I/O 操作较多的程序,这样的不一致就意味着需要进行大量的工程工作才能在平台间移植代码。正是因为这个原因,我们才引入了 Boost Filesystem Library。这个广泛使用的库提供了安全、可移植且易用的 C++ 接口,用于执行文件系统操作。可以从 Boost 站点免费下载此库。

使用 boost::filesystem 的第一个程序

在深入研究 Boost Filesystem Library 的更多细节之前,请看一下清单 1 中所示的代码;此代码使用 Boost API 确定某个文件的类型是否为 Directory。


清单 1. 用于确定某个文件的类型是否为 Directory 的代码
        #include <stdio.h>          #include “boost/filesystem.hpp”          int main()          {          boost::filesystem::path path("/usr/local/include"); // random pathname          bool result = boost::filesystem::is_directory(path);            printf(“Path is a directory : %d"n”, result);          return 0;          }          

此代码非常明了易懂,您并不需要了解任何系统特定的例程。此代码经过验证,能在不用修改的情况下在 gcc-3.4.4 和 cl-13.10.3077 上成功编译。

了解 Boost path 对象

了解 Boost Filesystem Library 的关键是 path 对象,因为 Filesystem Library 中定义的多个例程都要对相应的 path 对象操作。文件系统路径通常依赖于操作系统。例如,众所周知,UNIX 和 Linux 系统使用正斜杠 ( /) 字符作为目录分隔符,而 Windows 将反斜杠 (") 字符用于类似的用途。boost::filesystem::path 旨在准确地抽象此特性。path 对象可以通过多种方式进行初始化,最常见的方式是使用 char* 或 std::string 进行初始化,如清单 2 中所示。


清单 2. 创建 Boost path 对象的方法
        path(); // empty path            path(const char* pathname);           path(const std::string& pathname);          path(const char* pathname, boost::filesystem::path::name_check checker);           path(const char* pathname, boost::filesystem::path::name_check checker);           

在初始化 path 对象时,可以采用本机格式或可移植操作系统接口(Portable Operating System Interface,POSIX)委员会定义的可移植格式提供 PATHNAME 变量。这两种方法在实际中各有优缺点。考虑以下情况:您希望操作软件所创建的目录,此目录在 UNIX 和 Linux 系统上位于 /tmp/mywork,而在 Windows 上位于 C:"tmp"mywork。可以采用多种方法处理问题。清单 3 显示了面向本机格式的方法。


清单 3. 使用本机格式初始化 path
        #ifdef UNIX          boost::filesystem::path path("/tmp/mywork");          #else          boost::filesystem::path path("C:""tmp""mywork ");          #endif          

需要单个 #ifdef 来按操作系统初始化 path 对象。不过,如果您喜欢使用可移植格式,请参见清单 4


清单 4. 使用可移植格式初始化 path
        boost::filesystem::path path("/tmp/mywork");          

请注意,path::name_check 指的是一个名称检查函数原型。如果其参数输入 PATHNAME 对于特定的操作系统或文件系统有效,名称检查函数将返回“True”。Boost Filesystem Library 提供了多个名称检查函数,而且也欢迎您提供自己的变体。常用的名称检查函数是 Boost 提供的 portable_posix_name 和 windows_name

path 成员函数概述

path 对象提供了多个成员方法。这些成员例程并不会修改文件系统,但会根据 path 名称提供有用的信息。此部分提供了其中几个例程的概述:

  • const std::string& string( )此例程会返回用于初始化 path 的字符串的副本,其格式符合 path 语法规则。
  • std::string root_directory( )在提供了路径的情况下,此 API 将返回根目录,否则将返回空字符串。例如,如果路径包含 /tmp/var1,则此例程将返回 /,即 UNIX 文件系统的根。不过,如果路径是相对路径,如 ../mywork/bin,此例程将返回空字符串。
  • std::string root_name( )在给定从文件系统根目录开始的路径的情况下,此例程将返回包含 PATHNAME 的第一个字符的字符串。
  • std::string leaf( )在给定绝对路径名称(例如,/home/user1/file2)的情况下,此例程将提供与文件名称对应的字符串(即 file2)。
  • std::string branch_path( )这是与 leaf 互补的例程。在给定路径的情况下,将会返回其构造所用的所有元素(除了最后一个元素)。例如,对于使用 /a/b/c 初始化的 path,path.branch_path( ) 将返回 /a/b。对于包含单个元素的路径,如 c,此例程将返回空字符串。
  • bool empty( )如果 path 对象包含空字符串(例如 path path1("")),则此例程将返回 True。
  • boost::filesystem::path::iterator此例程用于遍历 path 的各个元素。请看清单 5 所示的代码。 

    清单 5. 使用 path::iterator(begin 和 end 接口)
                #include <iostream>              #include “boost/filesystem.hpp”              int main()              {              boost::filesystem::path path1("/usr/local/include"); // random pathname              boost::filesystem::path::iterator pathI = path1.begin();              while (pathI != path1.end())              {              std::cout << *pathI << std::endl;              ++pathI;              }              return 0;              }              // result: 1              

    上述程序的输出依次是 /usrlocalinclude,代表了该目录的层次结构。

  • path operator / (char* lhs, const path& rhs)此例程是 path 的非成员函数。它将返回使用 lhs 和 rhs 形成的路径的串联值。它将自动插入 / 作为路径分隔符,如清单 6 中所示。 

    清单 6. 路径字符串的串联
                #include <iostream>              #include “boost/filesystem.hpp”              int main()              {              boost::filesystem::path path1("/usr/local/include"); // random pathname              boost::filesystem::path::iterator pathI = path1.begin();              while (pathI != path1.end())              {              std::cout << *pathI << std::endl;              ++pathI;              }              return 0;              }              

    // result: 1

错误处理

文件系统操作经常遇到意外的问题,Boost Filesystem Library 将使用 C++ 异常报告运行时错误。boost::filesystem_error 类派生自 std::runtime_error 类。库中的函数使用filesystem_error 异常报告操作错误。与不同的可能错误类型对应,Boost 头文件定义了相应的错误代码。用户代码通常驻留在 try...catch 块内,使用 filesystem_error 异常来报告相关错误消息。清单 7 提供了重命名文件的小示例,在 from 路径中的文件不存在时引发异常。


清单 7. Boost 中的错误处理
                           #include <iostream>          #include “boost/filesystem.hpp”           int main()           {          try {          boost::filesystem::path path("C:""src""hdbase""j1");           boost::filesystem::path path2("C:""src""hdbase""j2");           boost::filesystem::rename(path, path2);          }          catch(boost::filesystem::filesystem_error e) {           // do the needful           }              return 0;          }          

Boost Filesystem Library 中的函数类别

boost::filesystem 提供了不同类别的函数:有些函数(如 is_directory)用于查询文件系统,而其他函数(如 create_directory)则主动对文件系统进行修改。根据各自功能的不同,这些函数可以大略归入以下类别:

  • 属性函数:提供杂项信息,如文件大小、磁盘使用量等。
  • 文件系统操作函数:用于创建常规文件、目录和符号链接;复制和重命名文件;提供删除功能。
  • 实用工具:测试文件的扩展名等。
  • 杂项常规函数:以编程方式更改文件扩展名等。

属性函数

Boost Filesystem Library 包括以下属性函数:

  • uintmax_t file_size(const path&)返回常规文件的大小(以字节为单位)
  • boost::filesystem::space_info space(const path&)接受路径作为输入,并返回定义如下的 space_info 结构:
                struct space_info {               uintmax_t capacity;              uintmax_t free;              uintmax_t available;              }; 根据文件系统所属的磁盘分区,此流程将对该分区的所有目录返回相同的磁盘使用量统计数据(以字节为单位)。例如,对于 C:"src"dir1 和 C:"src"dir2,都会返回相同的磁盘使用数据。
  • std::time_t last_write_time(const path&)返回文件的最后修改时间。
  • void last_write_time(const path&, std::time_t new_time)修改文件的最后修改时间。
  • const path& current_path( )返回程序的当前工作目录的完整路径(注意,此路径与最初运行程序的路径可能不同,因为可能采用编程方式更改目录)。

文件系统操作函数

这组函数负责进行新文件和目录创建、文件删除等操作:

  • bool create_directory(const path&)此函数使用给定的路径名称创建目录。(请注意,如果 PATHNAME 本身包含无效字符,则结果经常是由平台定义的。例如,在 UNIX 和 Windows 系统中,星号 (*)、问号 (?) 及其他此类字符视为无效,不能出现在目录名称中。)
  • bool create_directories(const path&)与创建单个目录相对,您可以使用此 API 创建目录树。例如,以目录树 /a/b/c 为例,必须在 /tmp 文件夹内创建此目录树。可调用此 API 完成任务,但使用相同的参数调用 create_directory 时将引发异常。
  • bool create_hard_link (const path& frompath, const path& topath)此函数在 frompath 和 topath 间创建硬链接。
  • bool create_symlink(const path& frompath, const path& topath)此函数在 frompath 和 topath 间创建符号(软)链接。
  • void copy_file(const path& frompath, const path& topath)frompath 引用的文件的内容和属性复制到 topath 引用的文件中。例程expects a destination file to be absent;如果存在目标文件,则会引发异常。因此,此函数与 UNIX 中系统指定的 cp 命令并不等效。另外,此函数还预期 frompath 变量将引用正确的常规文件。请看以下示例:frompath 引用符号链接 /tmp/file1,而后者反过来引用文件 /tmp/file2;而 topath 可以为 /tmp/file3。在这种情况下,copy_file 将失败。这是此 API 与 cp 命令相比的另一个差别。
  • void rename(const path& frompath, const path& topath)此函数是用于重命名文件的 API。可以通过在 topath 参数中指定完整路径名来同时重命名和更改文件的位置,如清单 8 中所示。 

    清单 8. Boost 中的重命名功能
                #include <stdio.h>              #include “boost/filesystem.hpp”              int main()              {              boost::filesystem::path path("/home/user1/abc");               boost::filesystem::rename(path, "/tmp/def");                return 0;              }              // abc is renamed def and moved to /tmp folder              

  • bool remove(const path& p)此例程将尝试删除路径 p 所引用的文件或目录。对于目录的情况,如果目录的内容不为空,则此例程将引发异常。警告:此例程并不考虑所删除的内容,即使其他程序在访问同一文件也如此!
  • unsigned long remove_all(const path& p)此 API 尝试删除路径 p 所引用的文件或目录。与 remove 不同,此函数并不会特殊考虑不为空的目录。此函数是 UNIXrm –rf 命令的 Boost 对等项。

实用工具

Boost Filesystem Library 包含以下实用工具:

  • bool exists(const path&)此函数检查文件的扩展名。文件可以为任何类型:常规文件、目录、符号链接等等。
  • bool is_directory(const path&)此函数检查路径是否与目录对应。
  • bool is_regular(const path&)此函数检查普通文件(即此文件不是目录、符号链接、套接字或设备文件)。
  • bool is_other(const path&)通常,此函数检查设备文件(如 /dev/tty0)或套接字文件。
  • bool is_empty(const path&)如果路径与文件夹对应,此函数将检查文件夹是否为空,并据此返回“True”或“False”。如果路径与文件对应,此函数将检查文件的大小是否等于 0。对于文件的硬链接或符号链接的情况,此 API 将检查原始文件是否为空。
  • bool equivalent(const path1& p1, const path2& p2)此 API 非常实用,可用于比较相对路径和绝对路径名。请看清单 9: 

    清单 9. 测试两个路径是否等效
                #include <stdio.h>              #include “boost/filesystem.hpp”              int main()              {              boost::filesystem::path path1("/usr/local/include"); // random pathname              boost::filesystem::path path2("/tmp/../usr/local/include");              bool result = boost::filesystem::is_equivalent(path1, path2);                printf(“Paths are equivalent : %d"n”, result);              return 0;              }              // result: 1              
  • path system_complete(const path&)此函数是与 bool equivalent(const path1& p1, const path2& p2) 同一系列的另一个 API。在给定当前工作目录中任意文件路径的情况下,此 API 将返回该文件的绝对路径。例如,如果用户位于目录 /home/user1 并查询文件 ../user2/file2,此函数将返回 /home/user2/file2,即文件 file2 的完整路径名。

杂项函数

Boost Filesystem Library 包括以下杂项函数:

  • std::string extension(const path&)此函数以前面带句点 (.) 的形式返回给定文件名的扩展名。例如,对于文件名为 test.cpp 的文件,extension 将返回 .cpp。对于文件没有扩展名的情况,此函数将返回空字符串。对于隐藏文件(即 UNIX 系统中文件名以 . 开始的文件),此函数将相应地计算扩展名类型或返回空字符串(因此,对于 .test.profile,此例程将返回 .profile)。
  • std::string basename(const path&)这是与 extension 互补的例程。它将返回文件名中 . 之前的字符串。请注意,即使提供了绝对文件名,此 API 仍然仅会返回属于文件名的直接部分,如清单 10 中所示。 

    清单 10. 使用 boost::basename
                #include <stdio.h>              #include <cstring>              #include “boost/filesystem.hpp”              use namespace std;              int main()              {              boost::filesystem::path path1("/tmp/dir1/test1.c ");               boost::filesystem::path path2("/tmp/dir1/.test1.profile");              string result1 = boost::filesystem::basename (path1);                string result2 = boost::filesystem::basename (path2);              printf(“Basename 1: %s  Basename2 : %s"n”, result1.c_str(), result2.c_str());              return 0;              }              // result: Basename1: test1 Basename2: .test1              
  • std::string change_extension(const path& oldpath, const std::string new_extension)此 API 将返回反映更改后的名称的新字符串。请注意,与 oldpath 对应的文件保持不变。这只是一个常规函数。另请注意,您必须显式地在扩展名中指定。例如,change_extension("test.c", "so") 会得到 testso,而不是 test.so
from the boost.org

Introduction

The Boost.Filesystem library provides portable facilities to query and manipulate paths, files, and directories.

The motivation for the library is the need to perform portable script-like operations from within C++ programs. The intent is not to compete with Python, Perl, or shell languages, but rather to provide portable filesystem operations when C++ is already the language of choice. Thedesign encourages, but does not require, safe and portable usage.

Programs using the library are portable, both in the sense that the syntax of program code is portable, and the sense that the semantics or behavior of code is portable. The generic path grammar is another important aid to portability.

Usage is safe in the sense that errors cannot be ignored since most functions throw C++ exceptions when errors are detected. This is also convenient for users because it alleviates the need to explicitly check error return codes.

A proposal, N1975, to include Boost.Filesystem in Technical Report 2 has been accepted by the C++ Standards Committee. The Boost.Filesystem library will stay in alignment with the TR2 Filesystem proposal as it works its way through the TR2 process. Note, however, that namespaces and header granularity differs between Boost.Filesystem and the TR2 proposal.

The Boost.Filesystem library provides several  headers:

  • Header <boost/filesystem.hpp> provides class basic_path, a portable mechanism for representing paths in C++ programs. Typedefs path and wpath ease the most common usages of basic_path. Operational functions provide useful query and maintenance operations on files and directories. Class basic_directory_iterator with typdefsdirectory_iterator and wdirectory_iterator provide iteration over the contents of directories. Convenience functions and classes combine lower-level functionality in useful ways.
     
  • Header <boost/filesystem/fstream.hpp> provides the same components as the C++ Standard Library's fstream header, except that files are identified by basic_pathobjects rather that char *'s.

Using the library

Boost.Filesystem is implemented as a separately compiled library, so before using it you must install it in a location that can be found by your linker. See Building the object-library.

The library's example directory contains very simple scripts for building the example programs on various platforms. You can use these scripts to see what's needed to compile and link your own programs.

Two-minute tutorial

(A more elaborate tutorial is also available from Tabrez Iqbal.)

First some preliminaries:

#include "boost/filesystem.hpp"   // includes all needed Boost.Filesystem declarations  #include <iostream>               // for std::cout  using boost::filesystem;          // for ease of tutorial presentation;  //  a namespace alias is preferred practice in real code

class path object can be created:

path my_path( "some_dir/file.txt" );

The string passed to the path constructor may be in a portable generic path format or an implementation-defined native operating system format. Access functions make my_pathcontents available to the underlying operating system API in an operating system dependent format, such as "some_dir:file.txt""[some_dir]file.txt""some_dir/file.txt", or whatever is appropriate for the operating system. If class wpath is used instead of class path, translation between wide and narrow character paths is performed automatically if necessary for the operating system.

Class path has conversion constructors from const char* and const std:: string&, so that even though the Filesystem Library functions used in the following code snippet have const path&formal parameters, the user can just code C-style strings as actual arguments:

remove_all( "foobar" );  create_directory( "foobar" );  ofstream file( "foobar/cheeze" );  file << "tastes good!"n";  file.close();  if ( !exists( "foobar/cheeze" ) )  std::cout << "Something is rotten in foobar"n";

To make class path objects easy to use in expressions, operator/ appends paths:

ifstream file1( arg_path / "foo/bar" );  ifstream file2( arg_path / "foo" / "bar" );

The expressions arg_path / "foo/bar" and arg_path / "foo" / "bar" yield identical results.

Paths can include references to the current directory, using "." notation, and the parent directory, using ".." notation.

Class basic_directory_iterator is an important component of the library. It provides an input iterator over the contents of a directory, with the value type being class basic_path. Typedefsdirectory_iterator and wdirectory_iterator are provided to cover the most common use cases.

The following function, given a directory path and a file name, recursively searches the directory and its sub-directories for the file name, returning a bool, and if successful, the path to the file that was found.  The code below is extracted from a real program, slightly modified for clarity:

bool find_file( const path & dir_path,         // in this directory,  const std::string & file_name, // search for this name,  path & path_found )            // placing path here if found  {  if ( !exists( dir_path ) ) return false;  directory_iterator end_itr; // default construction yields past-the-end  for ( directory_iterator itr( dir_path );  itr != end_itr;  ++itr )  {  if ( is_directory(itr->status()) )  {  if ( find_file( itr->path(), file_name, path_found ) ) return true;  }  else if ( itr->leaf() == file_name ) // see below  {  path_found = itr->path();  return true;  }  }  return false;  }

The expression itr->path().leaf() == file_name, in the line commented // see below, calls theleaf() function on the path returned by calling the path() function of the directory_entry object pointed to by the iterator. leaf() returns a string which is a copy of the last (closest to the leaf, farthest from the root) file or directory name in the path object.

In addition to leaf(), several other function names use the tree/root/branch/leaf metaphor.

Notice that find_file() does not do explicit error checking, such as verifying that the dir_pathargument really represents a directory. Boost.Filesystem functions throw exceptions if they do not complete successfully, so there is enough implicit error checking that this application doesn't need to supply additional error checking code unless desired. Several Boost.Filesystem functions have non-throwing versions, to ease use cases where exceptions would not be appropriate.

Note: Recursive directory iteration was added as a convenience function after the above tutorial code was written, so nowadays you don't have to actually code the recursion yourself.

Cautions

After reading the tutorial you can dive right into simple, script-like programs using the Filesystem Library! Before doing any serious work, however, there a few cautions to be aware of:

Effects and Postconditions not guaranteed in the presence of race-conditions

Filesystem function specifications follow the C++ Standard Library form, specifying behavior in terms of effects and postconditions. If a race-condition exists, a function's postconditions may no longer be true by the time the function returns to the caller.

Explanation: The state of files and directories is often globally shared, and thus may be changed unexpectedly by other threads, processes, or even other computers having network access to the filesystem. As an example of the difficulties this can cause, note that the following asserts may fail:

assert( exists( "foo" ) == exists( "foo" ) );  // (1)

remove_all( "foo" );
assert( !exists( "foo" ) );  // (2)

assert( is_directory( "foo" ) == is_directory( "foo" ) ); // (3)

(1) will fail if a non-existent "foo" comes into existence, or an existent "foo" is removed, between the first and second call to exists(). This could happen if, during the execution of the example code, another thread, process, or computer is also performing operations in the same directory.

(2) will fail if between the call to remove_all() and the call to exists() a new file or directory named "foo" is created by another thread, process, or computer.

(3) will fail if another thread, process, or computer removes an existing file "foo" and then creates a directory named "foo", between the example code's two calls to is_directory().

May throw exceptions

Unless otherwise specified, Boost.Filesystem functions throw basic_filesystem_errorexceptions if they cannot successfully complete their operational specifications. Also, implementations may use C++ Standard Library functions, which may throw std::bad_alloc. These exceptions may be thrown even though the error condition leading to the exception is not explicitly specified in the function's "Throws" paragraph.

All exceptions thrown by the Filesystem Library are implemented by callingboost::throw_exception(). Thus exact behavior may differ depending on BOOST_NO_EXCEPTIONS at the time the filesystem source files are compiled.

Non-throwing versions are provided of several functions that are often used in contexts where error codes may be the preferred way to report an error.

Example programs

simple_ls.cpp

The example program simple_ls.cpp is given a path as a command line argument. Since the command line argument may be a relative path, the complete path is determined so that messages displayed can be more precise.

The program checks to see if the path exists; if not a message is printed.

If the path identifies a directory, the directory is iterated through, printing the name of the entries found, and an indication if they are directories. A count of directories and files is updated, and then printed after the iteration is complete.

If the path is for a file, a message indicating that is printed.

Try compiling and executing simple_ls.cpp to see how it works on your system. Try various path arguments to see what happens.

file_size.cpp

This example program prints the file's size if it is a regular file.

Other examples

The programs used to generate the Boost regression test status tables use the Filesystem Library extensively.  See:

  • process_jam_log.cpp
  • compiler_status.cpp

Test programs are sometimes useful in understanding a library, as they illustrate what the developer expected to work and not work. See:

  • wide_test.cpp
  • path_test.cpp
  • operations_test.cpp
  • fstream_test.cpp

Implementation

The current implementation supports operating systems which provide either the POSIX or Windows API.

The library is in regular use on Apple OS X, HP-UX, IBM AIX, Linux, Microsoft Windows, SGI IRIX, and Sun Solaris operating systems using a variety of compilers.

Macros

Users may defined the following macros if desired. Sensible defaults are provided, so users can ignore these macros unless they have special needs.

Macro NameDefaultEffect if definedBOOST_WINDOWS_APIDefined if Windows is detected by Boost.System's automatic configuration code, otherwise not defined.Implementation uses the Microsoft Windows native application program interface (API).BOOST_POSIX_APIDefined if Windows is not detected by Boost.System's automatic configuration code.Implementation uses the POSIX native application program interface (API).BOOST_FILESYSTEM_DYN_LINKDefined ifBOOST_ALL_DYN_LINK is defined, otherwise not defined.Boost.System library is dynamically linked. If not defined, static linking is assumed.BOOST_FILESYSTEM_NO_LIBDefined if BOOST_ALL_NO_LIBis defined, otherwise not defined.Boost.System library does not use the Boost auto-link facility.BOOST_FILESYSTEM_NARROW_ONLYNot defined.Removes features that require wchar_t support.BOOST_FILESYSTEM_NO_DEPRECATEDNot defined.Deprecated features are excluded.

Deprecated names and features

As the library evolves over time, names sometimes change or features are removed. To ease transition, Boost.Filesystem deprecates the old names and features, but continues to provide them unless macroBOOST_FILESYSTEM_NO_DEPRECATED is defined.

Component

Old name, now deprecated

New name

basic_pathleaf()filename()basic_pathbranch_path()parent_path()basic_pathhas_leaf()has_filename()basic_pathhas_branch_path()has_parent_path()basic_path

remove_leaf()

remove_filename()

basic_pathbasic_path( const string_type & str,
  name_check )
feature removedbasic_pathbasic_path( const string_type::value_type * s,
  name_check )
feature removedbasic_pathnative_file_string()file_string()basic_pathnative_directory_string()directory_string()basic_pathdefault_name_check_writable()feature removedbasic_pathdefault_name_check( name_check )feature removedbasic_pathdefault_name_check()feature removedbasic_pathcanonize()feature removedbasic_pathnormalize()feature removedoperations.hppis_regular( file_status f )is_regular_file( file_status f )operations.hppsymbolic_link_exists( const path & ph )feature removedbasic_directory_statusfilename()feature removed, use path().filename() insteadbasic_directory_statusleaf()feature removed, use path().filename() insteadbasic_directory_statusstring()feature removed, use path().string() instead

Restricting library to narrow character paths

Compilers or standard libraries which do not support wide characters (wchar_t) or wide character strings (std::wstring) are detected automatically, and cause the library to compile code that is restricted to narrow character paths (boost::filesystem::path). Users can force this restriction by defining the macro BOOST_FILESYSTEM_NARROW_ONLY. That may be useful for dealing with legacy compilers or operating systems。



2 文件时间:
BOOL GetFileTime(
  HANDLE hFile,                 // handle to the file
  LPFILETIME lpCreationTime,    // address of creation time
  LPFILETIME lpLastAccessTime,  // address of last access time
  LPFILETIME lpLastWriteTime    // address of last write time
);


The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601. 

//nanosecond 是 10亿分之一,我倒。

typedef struct _FILETIME { // ft 
    DWORD dwLowDateTime; 
    DWORD dwHighDateTime; 
} FILETIME; 


FileTimeToSystemTime
The FileTimeToSystemTime function converts a 64-bit file time to system time format. 

BOOL FileTimeToSystemTime(
  CONST FILETIME *lpFileTime,  // pointer to file time to convert
  LPSYSTEMTIME lpSystemTime    // pointer to structure to receive 
                               // system time
);

typedef struct _SYSTEMTIME {  // st 
    WORD wYear; 
    WORD wMonth; 
    WORD wDayOfWeek; 
    WORD wDay; 
    WORD wHour; 
    WORD wMinute; 
    WORD wSecond; 
    WORD wMilliseconds; //这个是毫秒吧?
} SYSTEMTIME; 

__int64 FileTimeToQuadWord(PFILETIME pFileTime) 

    __int64 qw; 
    qw = pFileTime->dwHighDateTime; 
    qw <<= 32; 
    qw |= pFileTime->dwLowDateTime; 
    return (qw); 


PFILETIME QuadWordToFileTime(__int64 qw,PFILETIME pFileTime) 

    pFileTime->dwHighDateTime = (DWORD)(qw >> 32); 
    pFileTime->dwLowDateTime = (DWORD)(qw & 0xFFFFFFFF); 
    return (pFileTime); 


//

0 0
原创粉丝点击