BOOST 庫中filesyatem 庫的學習

ye34 9年前發布 | 49K 次閱讀 Boost C/C++開發

/*FileSyatem 庫的學習
------------------------------------------------------------------------------------------------------------庫的使用方式
嵌入源碼的形式:

define BOOST_SYSTEN_NO_LIB

define BOOST_FILESYSTEM_NO_LIB

include<boost\filesystem.hpp>

-----------------------------------------------------------------------------------------------------------類摘要 filesystem 庫的核心類是basic_path 通常我們不直接使用basic_path而是使用預定義的path和wpath typedef basic_path<std::string,path_traits>path; ------------------------------------------------------------------------------------------------------------路徑表示 posix 語法使用斜杠(/)來分隔文件名和目錄名,點號(.)表示當前目錄,雙點號(..)表示上一級目錄 path p1("./a_dir"); path p2("/usr/local/lib"); path也支持操作系統的原生路徑表示比如windows下使用盤符分隔符和反斜杠(\): path p3("c:\temp\test.text"); path p4("d:/boost/boostget"); 空的構造函數創建一個空路徑對象,不表示任何路徑,成員函數empty可以判斷路徑是否為空 path p5; assert(p.empty()); path 重載了operator/=可以使用普通路徑一樣用/來追加路徑,成員函數append()也可以追加一個字符串序列 char str[]="the path is (/root)."; path p(str+13,str+14); p/="etc";追加路徑 string filename="xinetd.conf"; p.append(filename.begin(),file.end()); 結果:p=/etc/xinetd.conf;

system_complete(p)返回路徑在當前文件系統中的完整文件路徑 --------------------------------------------------------------------------------------------------------------------可移植的文件名 filesystem提供了一系列的文件名檢查函數可以根據系統命名規則判斷一個文件字符串是否有效 portable_posix_name()和windows_name()分別檢查文件名是否符合POSIX規范和windows規范 函數portable_name()判斷名字是否是一個可移植的文件名但名字不能以點好或者連字符開頭,允許表示當前目錄的“。”和父目錄“..” protable_directory_name()包含了portable_name()并且要求名字不能出現點號 portable_file_name() 類似protable_directory_name()它要求文件名中最多有一個點號并且后綴名不能超過三個字符

filesystem 提供了一個native()函數它判斷文件名是否符合本地文件系統名規則在windows等同于windows_name(),其他操作系統知識簡單的判斷文件名不是空格且不含斜杠 ---------------------------------------------------------------------------------------------------------------------路徑處理 path的成員函數string()返回標準格式的路徑表示,directory_string()返回文件系統格式路徑表 示,parent_path(),stem(),filename()和extension()分別返回路徑中的父路徑,不含擴張名的全路徑名,文件名和 擴展名 is_complete()函數檢測path是否是一個完整的路徑(絕對路徑),這需要依據具體的文件(操作系統)系統表示 root_name()和root_directory(),root_path()三個函數用于根目錄的處理如果path中含有根那么他們分別返回根的名字,根目錄和根路徑 cout<<p.root_name()<<endl; cout<<p.root_directory()<<endl; cout<<p.root_path()<<endl; 這段代碼在linux下輸出一個空字符串和兩個斜杠(/),如果path是如C:/xx/yyy的形式輸出的會是 “C”,“/”,“C:/” relative_path()返回path的相對路徑相當于去掉了root_path() 根路徑和相對路徑的的四個函數都有對應的has_XXX()的形式,用來判斷是否存在對應的路徑 has_filename()和has_parent_path()用于判斷路徑是否有文件名或者父路徑 p.has_root_name() 可以修改path函數: remove_filename()可以移除路徑中的最后文件名,變成純路徑 replace_extension()可以變更文件的擴展名 可以對兩個path對象進行比較基于字典且對大小寫敏感 < > == != ----------------------------------------------------------------------------------------------------------------------------- 迭代路徑中的字符串 path還提供迭代器 begin()和end() path p="/boost/tools/libs" BOOST_AUTO(pos,p.begin()); while(pos!=p.end()) { cout<<"["<<*pos<<"]"; ++pos; } 結果[/][boost][tools][libs] 如果path類提供的這些操作還不能滿足要求可以使用boost庫中的字符串庫如string_algo -------------------------------------------------------------------------------------------------------------------------------- 異常 異常類是個模板類basic_filesystem_error它是system庫中system_error類的子類 我們通常應該使用這兩個預定義的異常類 typedef basic_filesystem_error<path> filesystemerror typedef basic_filesystem_error<path> wfilesystemerror --------------------------------------------------------------------------------------------------------------------使用 下面的代碼檢查文件大小但是文件不存在 path p("c:/test.txt") try { file_size(p); } catch(filesystem_error& e) { cout<<e.path1()<<endl; cout<<e.what()<<endl;

} ---------------------------------------------------------------------------------------------------------------------------------------- 文件狀態 filesystem庫提供一個文件狀態類file_status以及一組相關函數,用于檢查文件的各種屬性,如有是否存在是否是目錄,是否是符號鏈接等 file_status的成員函數type()用于獲取文件的狀態他是一個枚舉值通常我們不直接使用file_status而是使用使用相關的函數返回file_status對象 函數status(const Path&p)和symlink_status(const Path&p)測試路徑p的狀態結果可以type()如果路徑不能解析則拋出異常 file_type是枚舉值可以是以下值: file_not_found 文件不存在 status_unknow 文件存在但狀態未知 regular_file 是一個普通文件 directory_file 是一個目錄 symlink_file 是一個連接文件 block_file 一塊設備文件 character_file 一個字符設備文件 fifo_file 管道設備文件 socket_file socket設備文件 type_unknow 文件的類型未知 assert(status("d:/boost").type()==directory_file) filesystem 庫提供了一些便利的謂詞函數is_XXX以簡化文件狀態的判斷 assert(is_directory("d:/boost")) 大部分謂詞函數望文只意比較特別的是is_other()和is_empty()但文件不是普通文件,目錄或鏈接是,is_other()返回true 對于 empty若是目錄則里邊沒文件時返回true,若是文件 大小問0是返回true 函數 equivalent()可比較兩個目錄實體是否是同一個 ---------------------------------------------------------------------------------------------------------------------------------------- 文件屬性 受到移植性的限制filesystem提供少量的文件屬性操作 函數initial_path()函數返回程序啟動時(進入main())的當前路徑 函數current_path()返回當前路徑它和initial_path()都是返回完整路徑 函數file_size()以字節為單位返回文件的大小 函數last_write_time()返回文件最后修改時間是一個time_t 類型 函數space可以返回一個space_info它表明該路徑下的磁盤空間分配情況 struct space_info { uintmax_t capacity; uintmax_t free; uintmax_t available; } space()函數可以這樣使用 const int GBYTES=102410241024; space_info si=space("d:/"); cout<<si.capacity/GBYTES<<endl; cout<<si.available/GBYTES<<endl; --------------------------------------------------------------------------------------------------------------------------------- 文件操作 創建目錄 create_directory() 文件改名 rename() 文件刪除 remove(),remove_all()可以遞歸刪除所有文件對于remove使用時要加命名空間限制,否則vc環境下的函數會將其覆蓋

文件拷貝 copy_file() ........... ------------------------------------------------------------------------------------------------------------------迭代目錄 filesystem 庫使用basic_directory_iterator可以迭代目錄下所有文件 其預定義了兩個迭代器類 directory_iterator 和wdirectroy_iterator basic_directory_iterator迭代器返回的不是path對象而是basic_directory_entry對象,但是basic_directory_entry類定義了一個到path類的轉換函數 可以使用path()返回路徑 directory_iterator只能迭代本目錄中的文件不支持深度遍歷目錄但是可以通過遞歸實現 void recursive_dir(const path& dir) { directory_iterator end; for(directory_iterator pos(dir);pos!=end;++pos) if(is_directory(pos)) { recursive_dir(pos); } else cout<<*pos<<endl; }

basic_recursive_directory_iterator類提供了目錄的遍歷功能它比遞歸的調用directory_iterator效率要高 其基本功能和directory_iterator相似 通常我們使用其預定義的兩個類 recursive_directory_iterator和wrecursive_directory_iterator recursive_directory_iterator ++會使它返回目錄中的下一個文件 成員函數: level()返回當前目錄深度 m_level,recursive_directory_iterator構造時m_level=0每深入一層m_level加1退出時減少1 pop()用于退出當前目錄的遍歷同時--mlevel,但迭代到一個目錄no_push()可以讓目錄不參與遍歷 使用recursive_directory_iterator遍歷目錄操作 recursive_directory_iterator end; for(recursive_directory_iterator pos("d:/test");pos!=end;++pos) cout<<"level:"<<pos.level()<<":"<<pos<<endl; 使用no_push()讓recursive_directory_iterator和directory_iterator行為相同: directory_iterator end; for(recursive_directory_iterator pos(dir);pos!=end;++pos) if(is_directory(pos)) { pos.no_push(); } else cout<<pos<<endl; ---------------------------------------------------------------------------------------------------------------------------------------------- 文件流操作 filesystem 庫提供大量的文件系統操作方法,可以方便的操作文件或者目錄,但他使用的是path對象C++標準庫中的文件流類ifstream/ofstream/ftream只支持char打開文件,因此使用時我們必須 調用path對象的string()方法然后把string轉化為C字符串 path p("d:/boost/Readme.txt"); std::ifstream ifs(p.string().c_str()); filesystem 庫在額外的頭文件<boost/filesystem/fstream.hpp>中提供在命名空間boost::filesystem下的同文件流類他們可以如 標準文件流一樣使用而且支持path對象 使用方法:

include<>boost/filesystem/fstream.hpp>

namespace newfs=boost::filesystem; int main() { path p("d:/boost/readme.txt"); newfs::ifstream ifs(p.string().c_str()); assert(ifs.is_open()); cout<<ifs.rdbuf(); } --------------------------------------------------------------------------------------------------------------------------------------------- 實例一之文件查找

include<string>

include<boost/filesystem.hpp>

include<boost/optional.hpp>

using namespace std; using namespace boost::filesystem; using namespace boost; optional<path> find_file(const path& dir, const string&filename) { typedef optional<path> result_type; if (!exists(dir) || !is_directory(dir)) return result_type(); recursive_directory_iterator end; for (recursive_directory_iterator pos(dir); pos != end; ++pos) { if (!is_directory(*pos) && pos->path().filename() == filename) return result_type(pos->path()); } return result_type(); } void main() {

optional<path> r = find_file("G:\TEST", "1122.txt"); if (r) cout << *r << endl; else cout << "file not found" << endl;

} --------------------------------------------------------------------------------------------------------------------------------------- 實例二文件名的模糊查詢 void find_files(const path& dir, const string&filename,vector<path>v) { static xpressive::sregex_compiler rc;//正則表達式工廠 if (!rc[filename].regex_id()) { string str = replace_all_copy(replace_all_copy(filename, ".", "\."), "", ".");//處理文件名 rc[filename] = rc.compile(str);//創建正則表達式 } typedef vector<path> result_type; if (!exists(dir) || !is_directory(dir)) { return ; } recursive_directory_iterator end; for (recursive_directory_iterator pos(dir); pos != end; ++pos) { if (!is_directory(pos) && regex_match(pos->path().filename(), rc[filename])) { v.push_back(pos->path()); } } } ------------------------------------------------------------------------------------------------------------------------------------- 實例三目錄拷貝 size_t copy_files(const path& from_dir, const path& to_dir, const string& filename = "") { if (!is_directory(from_dir)) { cout << "args is not a dir" << endl; return 0; } cout << "prepare for copy,please wait......" << endl; vector<path>v; find_files(from_dir, filename, v); if (v.empty()) { cout << "0 file copied" << endl; return 0; } cout << "now begin copy files......" << endl; path tmp; progress_display pd(v.size()); BOOST_FOREACH(path& p, v)//for_each 算法 { tmp = to_dir / p.string().substr(from_dir.string().length()); if (!exists(tmp.parent_path())) create_directories(tmp.parent_path()); copy_file(p, tmp); ++pd; cout << v.size() << "file copied" << endl; return v.size(); }

} */</pre>

 本文由用戶 ye34 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!