当前位置:文档之家› 了解 Boost Filesystem Library

了解 Boost Filesystem Library

了解 Boost Filesystem LibraryC++语言(实际上是C++标准)的最常见问题之一是,缺乏定义良好的库来帮助处理文件系统查询和操作。

由于这个原因,程序员不得不使用本机操作系统提供的应用程序编程接口(Application Program Interfaces,API),而这使得代码不能在平台之间移植。

以下面的简单情况为例:您需要确定某个文件是否是Directory 类型。

在Microsoft® Windows® 平台中,可以通过调用GetAttributes库函数(在windows.h 头文件中定义)进行此操作:DWORD GetFileAttributes (LPCTSTR lpFileName);对于目录,所得到的结果应该为FILE_ATTRIBUTE_DIRECTORY,而您的代码必须检查是否为此结果。

在UNIX® 和Linux® 平台上,可以通过使用stat或fstat函数及sys/stat.h 中定义的S_ISDIR 宏来实现相同的功能。

您还必须理解stat结构。

下面是对应的代码:#include <sys/stat.h>#include <stdio.h>int main(){struct stat s1;int status = stat(<const char* denoting pathname>, &s1);printf(“Path is a directory : %d\n”, S_ISDIR(s1.st_mode));return 0;}对于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 pathnamebool 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 pathpath(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 UNIXboost::filesystem::path path("/tmp/mywork");#elseboost::filesystem::path path("C:\\tmp\\mywork ");#endif需要单个#ifdef来按操作系统初始化path 对象。

不过,如果您喜欢使用可移植格式,请参见清单4。

清单4. 使用可移植格式初始化pathboost::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 pathnameboost::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 pathnameboost::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)则主动对文件系统进行修改。

相关主题