boost::filesystem文件操作

#include <boost/filesystem.hpp>
#include <iostream>
#include <boost/ratio.hpp>
#include <map>
#include <vector>
#include <string>
#include <memory>
#include <boost/optional.hpp>
#include <boost/xpressive/xpressive.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/progress.hpp>

/**********************************************************
*使用boost::filesystem::director_iterator迭代當前目錄下文件(不向下層目錄迭代),但是也可實現目錄下層目錄循環遞歸,
*其實boost也提供了boost::filesystem::recursive_directory_iterator向下遞歸而且遍歷目錄是可控制的(深度/淺度),
*且速度比遞歸的director_itertaor快
***********************************************************/
void resource_direction(const boost::filesystem::path& path)
{
    //遞歸文件目錄下的所有文件路徑
    boost::filesystem::directory_iterator end;
    for(boost::filesystem::directory_iterator begin(path);begin!=end;begin++)
    {
        //如果是目錄繼續向下解析
        if (boost::filesystem::is_directory(*begin))
            resource_direction(*begin);
        else
            std::cout<<*begin<<std::endl;
    }
}

//boost filesystem realize find file
boost::optional<boost::filesystem::path> find_file(const boost::filesystem::path& path,const std::string& file)
{
    typedef boost::optional<boost::filesystem::path> result_value;
    if (!boost::filesystem::exists(path)&&!boost::filesystem::is_directory(path))
        return result_value();

    //遞歸目錄查找
    boost::filesystem::recursive_directory_iterator end;
    for(boost::filesystem::recursive_directory_iterator iter(path);iter!=end;++iter)
    {
        if (!boost::filesystem::is_directory(*iter)&&iter->path().filename()==file)
            return result_value(iter->path());
    }

    return result_value();
}

//boost filesystem realize obscure find file 利用boost::xpressive正則匹配實現模糊查找(只實現"*"匹配)
std::vector<boost::filesystem::path> obscure_find_file(const boost::filesystem::path &path, const std::string &file)
{
    //之後查找使用- -
    static boost::xpressive::sregex_compiler rc;         //正則表達式工廠
    if (!rc[file].regex_id())
    {
        std::string str = boost::replace_all_copy(boost::replace_all_copy(file, ".", "\\."), "*", ".*");
        rc[file] = rc.compile(str);
    }


    typedef std::vector<boost::filesystem::path> result_value;
    result_value v;
    if (!boost::filesystem::exists(path) && !boost::filesystem::is_directory(path))
    {
        return v;
    }

    //遞歸目錄查找
    boost::filesystem::recursive_directory_iterator end;
    for (boost::filesystem::recursive_directory_iterator iter(path); iter != end; ++iter)
    {
        if (!boost::filesystem::is_directory(*iter) &&
            boost::xpressive::regex_match(iter->path().filename().string(), rc[file]))
        {
            v.push_back(iter->path());
        }
    }

    return v;
}

std::size_t copy_files(const boost::filesystem::path &from_dir,  const boost::filesystem::path &to_dir,
                        const std::string &filename = "*")
{
    if (!boost::filesystem::exists(from_dir))
    {
        std::cout << "file not find" << std::endl;
        return -1;
    }


    std::cout << "prepare copy please wait....." << std::endl;
    auto vcontain = obscure_find_file(from_dir, filename);

    if (vcontain.empty())
    {
        std::cout << "file is empty" << std::endl;
        return -1;
    }


    boost::filesystem::path temp;
    boost::progress_display display(vcontain.size());

    for (auto &iter:vcontain)
    {
        temp = to_dir / iter.string().substr(from_dir.string().length());
        std::cout << "file: " << temp << std::endl;
        if (!boost::filesystem::exists(temp.parent_path()))
        {
            boost::filesystem::create_directories(temp.parent_path());
        }

        if(boost::filesystem::is_directory(iter))
        {
            boost::filesystem::create_directories(temp);
        }
        else{
            boost::filesystem::copy_file(iter, temp, boost::filesystem::copy_option::overwrite_if_exists);
        }

        ++display;
    }

    std::cout << vcontain.size() << " filed copyed" << std::endl;

    return vcontain.size();

}


int main()
{
    //filesystem basic
    //因爲文件屬於程序外的不可控資源,隨時拋出異常,try{}catch處理
    try
    {
        //unix
        boost::filesystem::path path1("./Demo/Demo.txt");
        //windows
        boost::filesystem::path path2("C:\\Boost\\Demo\\include\\");

        //空路徑,可用empty()判斷
        boost::filesystem::path path3;
        assert(path3.empty());

        //path構造時不會檢查路徑的合法性(可使用函數判斷)
        boost::filesystem::path path4("asdwqdqdasd");


        boost::filesystem::path path5("/usr/local/include/");
        auto path6 = path5 / "boost/filesystem/";                    //path重載了operator/()方法可追加路徑
        std::cout << path6 << std::endl;                             //path重載operator<<方法輸出
        std::cout << path6.string() << std::endl;                    //返回string的方法,可用於C++中的fstream
        std::cout << path6.parent_path() << std::endl; //父路徑
        std::cout << path6.filename() << std::endl; //文件
        std::cout << path6.stem() << std::endl; //不帶擴展名的文件名
        std::cout << path6.extension() << std::endl; //擴展名


        //唯一兩個可修改路徑函數
        path6.replace_extension("ini");     //修改文件後綴名
        std::cout << path6 << std::endl;                    //"/usr/local/include/boost/filesystem/.ini"
        path6.remove_filename();            //移除文件名
        std::cout << path6 << std::endl;                    //"/usr/local/include/boost/filesystem"

        //path中有begin 和 end 迭代器,可以循環得出目錄名
        for (auto &iter:path6)
        {
            std::cout << "[" << iter << "]" << std::endl;
        }
        /*["/"]
          ["usr"]
          ["local"]
          ["include"]
          ["boost"]
          ["filesystem"]*/
        //    for (boost::filesystem::path::iterator it = path6.begin(); it != path6.end(); ++it)
        //        std::cout << *it << std::endl;
        //    //path6 /= "/home/kerngeeksund/Documents";//將一個路徑添加到另一個之上 p /= path dengtongyu p = p / path
        //    std::cout << p.string() << std::endl;


        enum file_type
        {
            status_error,
        #ifndef BOOST_FILESYSTEM_NO_DEPRECATED
            status_unknown = status_error,
        #endif
            file_not_found,
            regular_file,
            directory_file,
            // the following may not apply to some operating systems or file systems
                    symlink_file,
            block_file,
            character_file,
            fifo_file,
            socket_file,
            reparse_file,  // Windows: FILE_ATTRIBUTE_REPARSE_POINT that is not a symlink
            type_unknown,  // file does exist, but isn't one of the above types or
            // we don't have strong enough permission to find its type

            _detail_directory_symlink  // internal use only; never exposed to users
        };

        std::cout << boost::filesystem::status(path6).type() << std::endl;              //文件類型
        std::cout << boost::filesystem::symlink_status(path6).type() << std::endl;
        std::cout << boost::filesystem::directory_file << std::endl;
        std::cout << boost::filesystem::status(path6).permissions() << std::endl;      //文件的權限等級
    }
    catch (boost::filesystem::filesystem_error &e)
    {
        std::cout << e.path1() << std::endl;
        std::cout << e.path2() << std::endl;
        std::cout << e.what() << std::endl;
    }

    //    查看磁盤和當前路徑,修改文件時間(linux::touch)
    //    因爲文件屬於程序外的不可控資源,隨時拋出異常,try{}catch處理
    try
    {
        boost::filesystem::path path("/Users/xuaidong/Desktop/test.txt");
        boost::filesystem::path path1("/Users/xuaidong");
        //進入(程序啓動時)main函數時的路徑
        std::cout << boost::filesystem::initial_path() << std::endl;
        //返回當前路徑,和initial_path()都是返回絕對路徑(完整路徑)
        std::cout << boost::filesystem::current_path() << std::endl;

        assert(boost::filesystem::is_regular_file(path));

        //返回文件最後一次修改時間
        std::cout << boost::filesystem::last_write_time(path) << std::endl;
        //更改文件修改時間(linux touch)
        boost::filesystem::last_write_time(path, time(0));
        std::cout << boost::filesystem::last_write_time(path) << std::endl;

        //查看磁盤空間
        boost::filesystem::space_info sp = boost::filesystem::space(path);
        std::cout << "磁盤空間: " << sp.capacity / boost::giga::num << std::endl;
        std::cout << "磁盤可用空間: " << sp.free / boost::giga::num << std::endl;
        std::cout << "磁盤可用空間: " << sp.available / boost::giga::num << std::endl;

        std::cout << boost::filesystem::file_size(path) << std::endl;
    }
    catch (boost::filesystem::filesystem_error &e)
    {
        std::cout << e.path1() << std::endl;
        std::cout << e.path2() << std::endl;
        std::cout << e.what() << std::endl;
    }

    //創建目錄,刪除目錄,拷貝文件
    //因爲文件屬於程序外的不可控資源,隨時拋出異常,try{}catch處理
    try
    {
        boost::filesystem::path path("/Users/xuaidong/Desktop/ABABAB");

        //assert(boost::filesystem::is_regular_file(path));
        assert(boost::filesystem::is_directory(path));

        //刪除空目錄/文件
        //boost::filesystem::remove(path);
        //遞歸刪除多個目錄或者文件
        boost::filesystem::remove_all(path);


        //根據path創建一個目錄
        boost::filesystem::create_directories(path);
        assert(boost::filesystem::exists(path));
        //拷貝文件到這個目錄下
        boost::filesystem::copy_file("/Users/xuaidong/Desktop/Some.txt", path / "Some2.txt");

        //重命名
        boost::filesystem::rename(path/"Some2.txt",path/"Demo.txt");

        //創建多及目錄
        boost::filesystem::create_directories(path/"Director1"/"Director2"/"Director3");


    }
    catch (boost::filesystem::filesystem_error &e)
    {
        std::cout << e.path1() << std::endl;
        std::cout << e.path2() << std::endl;
        std::cout << e.what() << std::endl;
    }

    //遍歷目錄
    //因爲文件屬於程序外的不可控資源,隨時拋出異常,try{}catch處理
    try
    {
        boost::filesystem::path path("/Users/xuaidong/Desktop/");
        resource_direction(path);

    }
    catch (boost::filesystem::filesystem_error &e)
    {
        std::cout << e.path1() << std::endl;
        std::cout << e.path2() << std::endl;
        std::cout << e.what() << std::endl;
    }

    //系統提供的文件目錄遍歷
    //因爲文件屬於程序外的不可控資源,隨時拋出異常,try{}catch處理
    try
    {
        std::map<int64_t, std::shared_ptr<std::vector<std::string>>> dir_map;
        //boost深度遍歷目錄和淺度遍歷
        //默認構造是尾迭代器
        boost::filesystem::recursive_directory_iterator end;
        for (boost::filesystem::recursive_directory_iterator iter("/Users/xuaidong/Desktop"); iter != end; iter++)
        {
            //std::cout << "directory_level: " << iter.level() << "file path: " << *iter << std::endl;
            if (boost::filesystem::is_directory(*iter))
            {
                iter.no_push();
            }             //不深度便利
            //iter.pop() 退出當前目錄的遍歷

            auto &ptr = dir_map[iter.level()];
            if (!ptr)
                ptr.reset(new std::vector<std::string>);

            ptr->push_back(iter->path().string());

        }

        for (auto &iter1:dir_map)
        {
            for (auto &iter2:*(iter1.second))
            {
                std::cout << "directory_level: " << iter1.first << ", file path: " << iter2 << std::endl;
            }
        }

    }
    catch (boost::filesystem::filesystem_error &e)
    {
        std::cout << e.path1() << std::endl;
        std::cout << e.path2() << std::endl;
        std::cout << e.what() << std::endl;
    }

    //實現簡單文件查找
    //因爲文件屬於程序外的不可控資源,隨時拋出異常,try{}catch處理
    try
    {
        auto path=find_file("/Users/xuaidong/Desktop/","application.cpp");

        if (path)
        {
            std::cout<<"CMakeLists.txt is here: "<<*path<<std::endl;
        }else
        {
            std::cout<<"CMakeLists.txt not to find"<<std::endl;
        }

    }
    catch (boost::filesystem::filesystem_error &e)
    {
        std::cout << e.path1() << std::endl;
        std::cout << e.path2() << std::endl;
        std::cout << e.what() << std::endl;
    }

    //利用boost::xpressive正則匹配實現模糊查找(只實現"*"匹配)
    //因爲文件屬於程序外的不可控資源,隨時拋出異常,try{}catch處理
    try
    {
        auto path = obscure_find_file("/home/kerngeeksund/Documents/", "*.txt");
        for (auto &iter:path)
        {
            std::cout << "file match: " << iter << std::endl;
        }
    }
    catch (boost::filesystem::filesystem_error &e)
    {
        std::cout << e.path1() << std::endl;
        std::cout << e.path2() << std::endl;
        std::cout << e.what() << std::endl;
    }

    //實現目錄文件拷貝(空目錄也拷貝)
    //因爲文件屬於程序外的不可控資源,隨時拋出異常,try{}catch處理
    try
    {
        copy_files("/home/kerngeeksund/Documents/Test1", "/home/kerngeeksund/Documents/Test2");
    }
    catch (boost::filesystem::filesystem_error &e)
    {
        std::cout << e.path1() << std::endl;
        std::cout << e.path2() << std::endl;
        std::cout << e.what() << std::endl;
    }

    return 0;

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章