Boostライブラリ学習(6)filesystem
C++の標準では、特定のファイルに対する読み書き操作方法のみが提供されており、ファイルパスに対する操作方法は定義されていないが、コードを記述する際に、ファイルパスを処理することが多い(ファイルが存在するかどうか、ファイルディレクトリをコピー、遍歴するなど).GUIプログラムであれば、QTのようなUIライブラリで提供されるファイルパス関連機能を使って、1つのコマンドラインプログラムだけでは面倒です.そこで今回はBoostのfilesystemライブラリを紹介します.Boostのfilesystemライブラリには、主にいくつかのファイル操作関数(ファイルプロパティのコピー、削除、読み取りなど)、1つのpathクラス(さまざまなファイルパスの変換)、2つのiterator(ディレクトリを巡るため)が含まれています.
ファイルディレクトリを巡回
新規ディレクトリ
Boostのfilesystemライブラリ自体は新規ディレクトリの関数を提供していますが、一つ不便な点は、「/home/user/abc/def」を新規に作成するには「/home/usre/abc」ディレクトリが必要なので、filesystemの関数を小さく閉じておきます.
パスリストで指定したファイルを検索
ソフトウェアがインストールされているかどうかを確認する必要がある場合がありますが、検出の最も簡単な方法は、ソフトウェアの実行可能なファイルが存在するかどうかを確認することです.例えばJDKをチェックするには、javacがあるかどうかを見ればいいのですが、ある会社なのかコミュニティが提供しているJDKなのかは重要ではありません.どこでjavacを探しますか?インストールパスは任意に指定できるので、環境変数PATHで指定されたパスで検索するのが一般的です.
一時ファイルの作成
完全なコードはdemo-filesystemディレクトリにあります.
ファイルディレクトリを巡回
<!-- lang: cpp -->
#include <boost/filesystem.hpp>
namespace bfs=boost::filesystem;
template<typename WalkAction> //
bool walk(const bfs::path& inpath, WalkAction action, bool recursive)
{
/* */
if (bfs::is_directory(inpath))
{
/* */
if (recursive)
{
for(auto entry=bfs::recursive_directory_iterator(inpath);
entry!=bfs::recursive_directory_iterator();++entry)
{
/* , action */
action(entry->path());
}
}
else
{
for(auto entry=bfs::directory_iterator(inpath);
entry!=bfs::directory_iterator();++entry)
{
/* action */
action(entry->path());
}
}
return true;
}
else
{
return false;
}
}
新規ディレクトリ
Boostのfilesystemライブラリ自体は新規ディレクトリの関数を提供していますが、一つ不便な点は、「/home/user/abc/def」を新規に作成するには「/home/usre/abc」ディレクトリが必要なので、filesystemの関数を小さく閉じておきます.
<!-- lang: cpp -->
void makedirs(const bfs::path& inpath)
{
/* */
/* absolute() canonical() */
/* canonical() ".." ".", */
bfs::path fpath=bfs::absolute(inpath);
/* */
if (!bfs::is_directory(inpath))
{
bfs::path cur;
/* fpath "/home/user/abc/def", fpath.begin() "/home",fpath.begin()+1 "user" */
for(auto item=fpath.begin();item!=fpath.end();++item)
{
/* */
cur/=*item;
if(bfs::is_directory(cur))
{
cur=bfs::canonical(cur);
}
else
{
/* */
bfs::create_directory(cur);
}
}
}
}
パスリストで指定したファイルを検索
ソフトウェアがインストールされているかどうかを確認する必要がある場合がありますが、検出の最も簡単な方法は、ソフトウェアの実行可能なファイルが存在するかどうかを確認することです.例えばJDKをチェックするには、javacがあるかどうかを見ればいいのですが、ある会社なのかコミュニティが提供しているJDKなのかは重要ではありません.どこでjavacを探しますか?インストールパスは任意に指定できるので、環境変数PATHで指定されたパスで検索するのが一般的です.
<!-- lang: cpp -->
void findInPath(const std::string& filename, std::initializer_list<std::string> additions, std::vector<bfs::path>& result, int count)
{
/* PATH */
std::string env(std::getenv("PATH"));
#ifdef WIN32
const std::string sep(";");
#else
const std::string sep(":");
#endif
std::string::size_type pos1(0),pos2;
std::vector<std::string> pathlist;
/* , */
pathlist.reserve(additions.size());
std::copy(additions.begin(),additions.end(),std::back_inserter(pathlist));
/* PATH, */
while(true)
{
pos2=env.find(sep,pos1);
if (std::string::npos==pos2)
{
if (env.size()-pos1>0)
{
pathlist.push_back(env.substr(pos1));
}
break;
}
else
{
if (pos2-pos1>0)
{
pathlist.push_back(env.substr(pos1,pos2-pos1));
}
pos1=pos2+1;
}
}
/* */
std::copy(pathlist.cbegin(),pathlist.cend(),
std::ostream_iterator<std::string>(std::cout,"
"));
/* */
for (auto &item:pathlist)
{
walk(bfs::path(item),
/* _saveToList result */
std::bind(_saveToList,std::placeholders::_1,std::ref(result),filename),
false);
if ((count>0) && (result.size()-count>=0))
{
break;
}
}
}
static void _saveToList(const bfs::path& file,std::vector<bfs::path>& vec,const std::string& filename)
{
if (file.filename().generic_string()==filename)
{
vec.push_back(file);
}
}
一時ファイルの作成
<!-- lang: cpp -->
/* */
bfs::path tmpfile("temp/abc/def");
makedirs(tmpfile);
/* */
tmpfile/=bfs::unique_path();
/* */
std::ofstream ofs(tmpfile.generic_string());
ofs<<"test
";
ofs.close();
/* */
bfs::remove_all("temp");
/* :
* copy, copy_directory, copy_file, copy_symlink
* copy copy_directory/copy_file/copy_symlink
* remove, remove_all
* remove ,remove_all
* rename
*/
完全なコードはdemo-filesystemディレクトリにあります.