一、文件和目录
boost::filesystem::path 提供的成员函数只是处理字符串。它们访问路径的各个组件,将路径相互附加,等等。
为了处理硬盘驱动器上的物理文件和目录,提供了几个独立的功能。他们期望一个或多个 boost::filesystem::path 类型的参数并在内部调用操作系统函数。
在介绍各种功能之前,重要的是要了解发生错误时会发生什么。所有函数都调用可能失败的操作系统函数。因此,Boost.Filesystem 提供了两种不同的函数变体,以防出错:
- 第一个变体抛出 boost::filesystem::filesystem_error 类型的异常。这个类派生自 boost::system::system_error,因此适合 Boost.System 框架。
- 第二个变体需要一个 boost::system::error_code 类型的对象作为附加参数。该对象通过引用传递,可以在函数调用后检查。在失败的情况下,对象存储相应的错误代码。
二、库应用案例
boost::system::system_error 和 boost::system::error_code 在第 55 章中介绍。除了从 boost::system::system_error 继承的接口之外,boost::filesystem::filesystem_error 还提供了两个名为 path1( ) 和 path2(),它们都返回 boost::filesystem::path 类型的对象。由于有些函数需要两个 boost::filesystem::path 类型的参数,因此这两个成员函数提供了一种在发生故障时检索相应路径的简单方法。
示例 35.10。使用 boost::filesystem::status()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\"};
try
{
file_status s = status(p);
std::cout << std::boolalpha << is_directory(s) << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
例 35.10 引入了 boost::filesystem::status(),它查询文件或目录的状态。此函数返回 boost::filesystem::file_status 类型的对象,可以将其传递给其他辅助函数进行评估。例如,如果查询目录的状态, boost::filesystem::is_directory() 返回 true。除了 boost::filesystem::is_directory(),还可以使用其他函数,包括 boost::filesystem::is_regular_file()、boost::filesystem::is_symlink() 和 boost::filesystem::exists()。它返回一个布尔类型的值。
函数 boost::filesystem::symlink_status() 查询符号链接的状态。使用 boost::filesystem::status() 可以查询符号链接引用的文件的状态。在 Windows 上,符号链接由文件扩展名 lnk 标识。
示例 35.11。使用 boost::filesystem::file_size()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\Windows\\win.ini"};
boost::system::error_code ec;
boost::uintmax_t filesize = file_size(p, ec);
if (!ec)
std::cout << filesize << '\n';
else
std::cout << ec << '\n';
}
不同类别的函数使查询属性成为可能。 boost::filesystem::file_size() 函数以字节为单位返回文件的大小。返回值是 boost::uintmax_t 类型,它是 unsigned long long 的类型定义。该类型由 Boost.Integer 提供。
示例 35.11 使用 boost::system::error_code 类型的对象,需要显式评估该对象以确定对 boost::filesystem::file_size() 的调用是否成功。
例 35.12。使用 boost::filesystem::last_write_time()
#include <boost/filesystem.hpp>
#include <iostream>
#include <ctime>
using namespace boost::filesystem;
int main()
{
path p{"C:\\Windows\\win.ini"};
try
{
std::time_t t = last_write_time(p);
std::cout << std::ctime(&t) << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
要确定文件最后修改的时间,可以使用 boost::filesystem::last_write_time() (参见示例 35.12)。
示例 35.13。使用 boost::filesystem::space()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\"};
try
{
space_info s = space(p);
std::cout << s.capacity << '\n';
std::cout << s.free << '\n';
std::cout << s.available << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
boost::filesystem::space() 检索总磁盘空间和剩余磁盘空间(参见示例 35.13)。它返回一个 boost::filesystem::space_info 类型的对象,它提供了三个公共成员变量:容量、空闲和可用,都是 boost::uintmax_t 类型。磁盘空间以字节为单位。
虽然到目前为止所介绍的函数并未触及文件和目录,但仍有几个函数可用于创建、重命名或删除文件和目录。
例 35.14。创建、重命名和删除目录
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\Test"};
try
{
if (create_directory(p))
{
rename(p, "C:\\Test2");
boost::filesystem::remove("C:\\Test2");
}
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
示例 35.14 应该是不言自明的。仔细观察,可以看到传递给函数的并不总是 boost::filesystem::path 类型的对象,而是一个简单的字符串。这是可能的,因为 boost::filesystem::path 提供了一个非显式构造函数,它将字符串转换为 boost::filesystem::path 类型的对象。这使得使用 Boost.Filesystem 变得很容易,因为它不需要显式创建路径。
注意
在示例 35.14 中, boost::filesystem::remove() 使用其命名空间显式调用。否则,Visual C++ 2013 会将该函数与头文件 stdio.h 中的 remove() 混淆。
其他功能,例如创建符号链接的 create_symlink() 或用于复制文件和目录的 copy_file() 和 copy_directory() 也可用。
示例 35.15。使用 boost::filesystem::absolute()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
try
{
std::cout << absolute("photo.jpg") << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
示例 35.15 展示了一个基于文件名或路径部分创建绝对路径的函数。显示的路径取决于程序启动的目录。例如,如果程序在 C:\ 中启动,则输出将为“C:\photo.jpg”。
要检索相对于不同目录的绝对路径,可以将第二个参数传递给 boost::filesystem::absolute()。
示例 35.16。创建相对于另一个目录的绝对路径
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
try
{
std::cout << absolute("photo.jpg", "D:\\") << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
示例 35.16 显示“D:\photo.jpg”。
本节的最后一个示例,示例 35.17,介绍了一个有用的帮助函数来检索当前工作目录。
示例 35.17。使用 boost::filesystem::current_path()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
try
{
std::cout << current_path() << '\n';
current_path("C:\\");
std::cout << current_path() << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
示例 35.17 多次调用 boost::filesystem::current_path()。如果不带参数调用函数,则返回当前工作目录。如果传递了 boost::filesystem::path 类型的对象,则设置当前工作目录。