filesystemの概要
filesystemはBoostに収録されたライブラリ:boost.filesystemをベースとし、今年末までには決まるはずの標準規格:C++17の一部となる予定。まだ仕様が確定していないので、Visual C++ 2015/2017に見つけたfilesystemは実験的(experimental)な実装であり、クラスや関数は名前空間:std::experimental::filesystemに置かれています。
filesystemのイケてるところをお見せするため、「カレント・ディレクトリ配下のファイル/ディレクトリを再帰的に列挙する」コードを書きました。
まずはWin32-API版。
#undef UNICODE #include <Windows.h> #include <iostream> #include <string> void walk_dir_recursive(const std::string& dir) { WIN32_FIND_DATA data; // 最初のエントリを探す(結果はdataに格納される) HANDLE handle = FindFirstFile((dir + "\\*.*").c_str(), &data); while ( handle != INVALID_HANDLE_VALUE ) { std::string filename = data.cFileName; if (filename != "." && filename != "..") { // . と .. は除外して filename = dir + "\\" + filename; // そのエントリがディレクトリなら if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { std::cout << "dir. " << filename << std::endl; walk_dir_recursive(filename); // さらに深く潜る } else { std::cout << "file " << filename << std::endl; } } // 次のエントリを探す。なかったらCloseしてwhile-loopを抜ける。 if ( !FindNextFile(handle, &data) ) { FindClose(handle); handle = INVALID_HANDLE_VALUE; } } } int main() { // カレント・ディレクトリから列挙開始 char current[260]; GetCurrentDirectory(260, current); walk_dir_recursive(current); }
FindFirstFile()でエントリの最初の一つを手に入れ、次のエントリを取り出すFindNextFile()を繰り返し、FindClose()で終了。取り出したエントリがディレクトリなら再帰的に呼び出してます、そこそこメンド臭いですね。こんな実行結果が得られます。
かたやfilesystemを使うと:
#include <filesystem> #include <iostream> namespace fs = std::experimental::filesystem; void walk_dir_recursive(const fs::path& dir) { for ( auto ent : fs::recursive_directory_iterator(dir) ) { std::cout << (fs::is_directory(ent) ? "dir. " : "file ") << ent << std::endl; } } int main() { // カレント・ディレクトリから列挙開始 walk_dir_recursive(fs::current_path()); }
たったこれだけでWin32版と同じ結果が得られます。