石头

我的备忘录

boost::filesystem指南

boost::filesystem指南

今天开始写作boost库指南系列文章了,我个人比较熟的就是这个filesystem库,当然要从这里先开始。这系列指南只是对初学的一个快速指南,没有深入学习,当然我个人水平也不敢说“深入”二字。

C++程序一直有一个方面不能做可移植性,尽管标准库有几个函数用于操作与文件系统相关的任务,但是这几个函数作用相对我们日常对文件系统操作的需求来说真是杯水车薪,所以对目录、路径、文件元信息的操作一直难以做可移植性。然而对于现在的程序来说,可移植性极端重要,谁也不保证他写程序不要某一天要移植更一个系统中去,可能这个系统现在大家还很少听说。

boost.filesystem为大家提供了一个选择。boost.filesystem以实现可移植的文件系统的操作为目标,通过精心设计一个中间概念来完成大多数可移植的文件系统的操作,这个中间层试图独立于所有的具体文件系统,然后把操作任务映射到这个中间层。当然这个中间层可能与现有的文件系统有最大的相似之处。本文不试图去讲述这个中间层,因为针对绝大部分情况,我们使用boost.filesystem不需要知道这个中间层。

下面我正式开始这个指南,这次好像扯得太远了。

基础知识

这里我们讲述一些使用库的基础的准备的知识。

  • filesystem库提供了两个头文件,一个是<boost/filesystem.hpp>,这个头文件包含主要的库内容。它提供了对文件系统的重要操作。同时它定义了一个类path,正如大家所想的,这个是一个可移植的路径表示方法,它是filesystem库的基础。
  • 一个是<boost/filesystem/fstream.hpp>,是对std::fstream的一个补充,使用可以使用类boost::path作为参数,从而使得filesystem库与标准库的关系更亲密。
  • 由于文件系统对于大多数系统来说都是共享的,所以不同的进程可以同时操作同一个对象,因此filesysetm不提供这方面的特性保证。当然这种保证也是不可能的,或者至少昂贵的。
  • filesystem在任何时候,只要不能完成相应的任务,它都可能抛出 basic_filesystem_error异常,当然并不是总会抛出异常,因为在库编译的时候可以关闭这个功能。同时有两个函数提供了无异常版本,这是因为在任务不能完成时并非是异常。
  • filesystem库的所有内容定义在boost名字空间的一个下级名字空间里,它叫boost::filesytem。在使用boost.filesytem之后,链接时需要加“-lboost_filesystem-mt”选项,因为这个需要额外的链接,并非一个纯头文件的库。

获得单独文件属性

有了上面的准备知识,大家可以写一些简单的程序了。这篇文档主要作为一个入门的指南性的文档,所以会提供许多实例,或者说主要以实体来说明的boost.filesystem库的使用。

/*
 * =====================================================================================
 *
 *       Filename:  filesystem.cpp
 *
 *    Description:  简单C++,boost filesystem 指南
 *
 *        Version:  1.0
 *        Created:  2009年08月17日 17时16分32秒
 *       Revision:  none
 *       Compiler:  gcc -Wall -Wextra filesystem.cpp -lboost_filesystem-mt
 *
 *         Author:  lgb (LiuGuangBao), easyeagel@gmx.com
 *        Company:  easy99.org
 *
 * =====================================================================================
 */


#include<iostream>
#include<fstream>
#include<boost/filesystem.hpp>

int main()
{
        namespace bf=boost::filesystem;//简单别名

        //filesystem中最基本的类型
        bf::path path("/tmp/test");

        //对当前的目录的操作
        bf::path old_cpath=bf::current_path(); //取得当前目录

        bf::path file_path = path / "file"; //path重载了 / 运算符

        //判断文件存在性
        if(bf::exists(path))
        {
                std::ofstream out(path.file_string().c_str());
                if(!out) return 1;
                out << "一个测试文件\n";
        } else {
                std::cout << path << "不存在\n";
                //目录不存在,创建
                bf::create_directory(path);
                std::ofstream out(file_path.file_string().c_str());
                if(!out) return 1;
                out << "一个测试文件\n";
        }

        bf::current_path(path); //设置当前为/home

        if(bf::is_regular_file(path))
        {
                std::cout << path << "是普通文件\n";
                std::cout << path << ": 大小为" << bf::file_size(path) <<'\n';
                bf::create_symlink(file_path, "/tmp/test/file-symlink");
        }

        bf::current_path(old_cpath);

        bf::remove(file_path);//删除文件file_path
        bf::remove_all(path);//递归地删除

        return 0;
}
上面的示例我们在Linux在测试通过,因为使用的是Linux系统。它首先创建一些东西,最后又把这些东西删除了,恢复原样了。

filesystem库使用经验

文件系统不具有许多特性与我们日常编写的程序不一样,标准库没有提供一个filesystem的原因就在于此,这个特殊性表现在:

  • 文件系统是操作系统级别上的全局性,即文件系统中的操作可以在多个进程中异步进行,这可能引起许多问题,也就是说文件系统不是串行系统。
  • 文件系统具有很大的系统相关性,不同的操作系统提供了不同的文件系统,相同的操作系统也可以存在众多区别。这使得编写具有可移植的文件系统相关程序很困难,这需要足够多的小心与细致。
  • 不要使用绝对路径,因为绝对路径系统相关性太强了,所以不可能在中间层透明地完成;应该使用相对路径。
  • boost::filesystem系统地定义了一个中间层,并且做到尽可能自由,但是有些问题是无法避免的。如UNIX系统存在符号链接的概念,而Windows中不存在,所以当你使用符号链接的时候就说明你不可能做到可移植性。

阅读更多
个人分类: boost
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭