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成员函数:
bool has_root_name() const;
bool has_root_directory() const;
bool has_relative_path() const;
bool has_filename() const;
bool has_branch_path() const;路经中是否包含指定的项
测试代码:
- #include "boost/filesystem.hpp" // 包含所有需要的 Boost.Filesystem 声明
- #include <iostream> // 使用 std::cout
- namespace fs = boost::filesystem;
- // 宏FSTEST:测试f的成员函数,输出成员函数名和结果
- #define FSTEST(x) std::cout << #x##": " << f.x << std::endl
- int main()
- {
- fs::path f("//folder1//folder2//folder3//filename.ext");
- FSTEST(string());
- FSTEST(file_string());
- FSTEST(directory_string());
- FSTEST(root_name());
- FSTEST(root_directory());
- FSTEST(root_path());
- FSTEST(relative_path());
- FSTEST(filename());
- FSTEST(parent_path());
- FSTEST(stem());
- FSTEST(extension());
- FSTEST(replace_extension("new"));
- char buf[]="hello";
- FSTEST(append(buf, buf+sizeof(buf)));
- FSTEST(remove_filename());
- return 0;
- }
输出:
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/
常用函数
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 迭代器对象,它是唯一一个用于结束条件的合法迭代器。示例代码,得到指定目录下的所有文件名:
- void find_file( const fs::path & dir_path )
- {
- if ( !fs::exists( dir_path ) ) return;
- fs::directory_iterator end_itr; // 缺省构造生成一个结束迭代器
- for ( fs::directory_iterator itr( dir_path );
- itr != end_itr;
- ++itr )
- {
- if ( fs::is_directory(itr->status()) )
- {
- find_file( itr->path() ); //递归查找
- }
- else
- {
- std::cout << *itr << std::endl;
- }
- }
- }
basic_recursive_directory_iterator
递归遍历目录的迭代器,它的构造参数与basic_directory_iterator相同,当调用 operator++
时,如果当前值是一个目录,则进入下一级目录。
它有三个成员函数:
示例代码,得到指定目录下的所有文件名(和上例作用相同):
- void find_file2( const fs::path & dir_path )
- {
- fs::recursive_directory_iterator end_itr; // 缺省构造生成一个结束迭代器
- for ( fs::recursive_directory_iterator itr( dir_path );
- itr != end_itr;
- ++itr )
- {
- std::cout << itr.level() << *itr << std::endl;
- }
- }
编译
使用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成员函数:
bool has_root_name() const;
bool has_root_directory() const;
bool has_relative_path() const;
bool has_filename() const;
bool has_branch_path() const;路经中是否包含指定的项
测试代码:
- #include "boost/filesystem.hpp" // 包含所有需要的 Boost.Filesystem 声明
- #include <iostream> // 使用 std::cout
- namespace fs = boost::filesystem;
- // 宏FSTEST:测试f的成员函数,输出成员函数名和结果
- #define FSTEST(x) std::cout << #x##": " << f.x << std::endl
- int main()
- {
- fs::path f("\\folder1\\folder2\\folder3\\filename.ext");
- FSTEST(string());
- FSTEST(file_string());
- FSTEST(directory_string());
- FSTEST(root_name());
- FSTEST(root_directory());
- FSTEST(root_path());
- FSTEST(relative_path());
- FSTEST(filename());
- FSTEST(parent_path());
- FSTEST(stem());
- FSTEST(extension());
- FSTEST(replace_extension("new"));
- char buf[]="hello";
- FSTEST(append(buf, buf+sizeof(buf)));
- FSTEST(remove_filename());
- return 0;
- }
输出:
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/
常用函数
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 迭代器对象,它是唯一一个用于结束条件的合法迭代器。示例代码,得到指定目录下的所有文件名:
- void find_file( const fs::path & dir_path )
- {
- if ( !fs::exists( dir_path ) ) return;
- fs::directory_iterator end_itr; // 缺省构造生成一个结束迭代器
- for ( fs::directory_iterator itr( dir_path );
- itr != end_itr;
- ++itr )
- {
- if ( fs::is_directory(itr->status()) )
- {
- find_file( itr->path() ); //递归查找
- }
- else
- {
- std::cout << *itr << std::endl;
- }
- }
- }
basic_recursive_directory_iterator
递归遍历目录的迭代器,它的构造参数与basic_directory_iterator相同,当调用operator++
时,如果当前值是一个目录,则进入下一级目录。它有三个成员函数:
示例代码,得到指定目录下的所有文件名(和上例作用相同):
- void find_file2( const fs::path & dir_path )
- {
- fs::recursive_directory_iterator end_itr; // 缺省构造生成一个结束迭代器
- for ( fs::recursive_directory_iterator itr( dir_path );
- itr != end_itr;
- ++itr )
- {
- std::cout << itr.level() << *itr << std::endl;
- }
- }
对于 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
上述程序的输出依次是
/
、usr
、local
、include
,代表了该目录的层次结构。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
。
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
A 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_API
Defined 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_API
Defined if Windows is not detected by Boost.System's automatic configuration code.Implementation uses the POSIX native application program interface (API).BOOST_FILESYSTEM_DYN_LINK
Defined 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_LIB
Defined if BOOST_ALL_NO_LIB
is defined, otherwise not defined.Boost.System library does not use the Boost auto-link facility.BOOST_FILESYSTEM_NARROW_ONLY
Not defined.Removes features that require wchar_t support.BOOST_FILESYSTEM_NO_DEPRECATED
Not 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.
Old name, now deprecated
New name
basic_path
leaf()
filename()
basic_path
branch_path()
parent_path()
basic_path
has_leaf()
has_filename()
basic_path
has_branch_path()
has_parent_path()
basic_path
remove_leaf()
remove_filename()
basic_path
basic_path( const string_type & str,
name_check )
feature removed
basic_path
basic_path( const string_type::value_type * s,
name_check )
feature removed
basic_path
native_file_string()
file_string()
basic_path
native_directory_string()
directory_string()
basic_path
default_name_check_writable()
feature removed
basic_path
default_name_check( name_check )
feature removed
basic_path
default_name_check()
feature removed
basic_path
canonize()
feature removed
basic_path
normalize()
feature removed
operations.hpp
is_regular( file_status f )
is_regular_file( file_status f )
operations.hpp
symbolic_link_exists( const path & ph )
feature removed
basic_directory_status
filename()
feature removed, use path().filename() instead
basic_directory_status
leaf()
feature removed, use path().filename() instead
basic_directory_status
string()
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。
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->dwHighDateTime = (DWORD)(qw >> 32);
pFileTime->dwLowDateTime = (DWORD)(qw & 0xFFFFFFFF);
return (pFileTime);
}
- Boost.Filesystem 使用 以及文件时间
- boost filesystem 使用
- boost::filesystem的文件遍历
- boost-文件路径操作filesystem
- boost库filesystem使用问题
- boost之filesystem的使用
- Boost::filesystem 使用小笔记
- Boost::filesystem的使用笔记
- boost::filesystem库使用入门
- Boost::filesystem 使用小笔记
- boost的filesystem使用示例
- <boost-02>如何使用boost::filesystem获取文件夹中的所有文件? how to use boost:: filesystem to get all files path?
- 使用boost.filesystem使用时编译错误
- boost::filesystem与CFile文件打开方式
- Boost Filesystem Library 路径 文件 目录
- boost.filesystem
- Boost.Filesystem
- boost filesystem
- VC++获取当前系统时间
- checkpoint not complete
- android launcher源码分析
- 循环逐条修改或者删除数据(游标)
- 爱就是赋予某人摧毁你的力量,却坚信他/她不会 伤害你。
- Boost.Filesystem 使用 以及文件时间
- oracle访问另一个数据库
- 解决在iframe中使用dialog可以在整个浏览器中移动
- 《找你妹2》开发者云中游再声明:热酷涉嫌严重违约发布侵权竞品
- JVM性能分析与优化
- Qt持久性对象进行序列化
- intellij vaadin archtypes
- SQL语句更新时间字段的年份、月份、天数、时、分、秒
- 论坛源码推荐(1月20日):加载解析RSS的Objective-C框架 Pininterest 弹出菜单的方式