はかせのラボ

私の頭の中を書いていく雑記ブログです

C++ ファイルI/Oが超絶楽になるfilesystem

あいさつ

どうも、はかせです。
前回フォルダ操作をWinAPIで実装してみた記事を上げました。
hakase0274.hatenablog.com

本日はフォルダ操作の続きということで
コピーとムーブをやろうとしたわけですが、
ここでとんでもない事実が発覚しました。

なんとC++17以降ならばfilesystemという
ヘッダーをインクルードすれば
めんどくさいWinAPIを使わずとも
ファイルI/Oができる
らしいです。

というわけで今回はfilesystemを使い
カレントディレクトリ取得、移動
フォルダ生成
フォルダ削除
フォルダコピー、移動
フォルダ階層取得

これらをやってみます。

環境

Windows10
VisualStudio2017
C++17

include

#include <iostream>
#include <fstream>
#include <Windows.h>
#include <filesystem>

カレントディレクトリ取得、移動

//取得
std::filesystem::path path = std::filesystem::current_path();
//移動
std::filesystem::current_path("移動後のパス");

カレントディレクトリ操作は
std::filesystem::current_path
を使用します。

引数無しで使えば現在のカレントディレクトリを取得し、
引数にパスを渡すことで移動をします。

手間はWinAPIと大差ないですが、
一つのメソッドの引数だけで動き変えれるのは楽でいいですね。

フォルダ生成

//フォルダ生成
std::filesystem::create_directory("フォルダ名");
//一気に作っちゃう
std::filesystem::create_directories("フォルダとその中のファイル等の名前をパスで入れる");

フォルダ生成には
std::filesystem::create_directory
std::filesystem::create_directories

この二つのメソッドがあります。

前者は単純にフォルダを生成します。
後者はフォルダと中身を同時に作ります。
同時に作れるのは楽ですね。

フォルダ削除

//削除(単一)
std::filesystem::remove("フォルダ名");
//削除(再帰的に中身も消す)
std::filesystem::remove_all("フォルダ名");

削除は
std::filesystem::remove
std::filesystem::remove_all

この二つです。

removeは中身あるとエラーになるので、
基本remove_allでいいのかなと思います。

フォルダコピー、移動

//コピー
std::filesystem::copy("コピー元", "コピー先");
//移動、改名
std::filesystem::rename("移動元", "移動先");

コピーには
std::filesystem::copyを使います。
コピーするのはファイルでもフォルダでも問題ないようです。

移動と改名は
std::filesystem::renameです。
移動の際には移動先のパスを別階層にしてあげれば移動になります。
同階層の場合移動元のファイル名が変わります。
こっちもフォルダ、ファイル問わずです。

ちなみにコピーも移動も
コピー先、移動先に指定したとこに、
ファイルが既にあった場合上書きではなくエラーになります。
(上書きする方法あるんかな・・)

コピーと移動がえげつないくらい楽になりましたね。
ファイル単位なら前もそんな変わりませんでしたが、
フォルダ単位になると何もなく、
フォルダを全走査してファイルならコピー、
フォルダなら生成して再帰的に処理を進めて・・・
みたいな感じでえらいめんどくさかったのを覚えています。

ちなみにファイル名走査はこっちでもやってます。
hakase0274.hatenablog.com

フォルダ階層取得

//フォルダ階層を取得
std::filesystem::directory_iterator e = std::filesystem::directory_iterator("CopyTest");
for (auto f : e) 
{
	std::cout << f.path().string() << std::endl;
}

階層取得は
std::filesystem::directory_iteratorで出来ます。

階層取得も先述のコピーとかと同じように
全走査するくらいしかなかったのにこんなに楽になって・・・
おまけにイテレータだから何かと扱いやすいし
神ですかねw

あとがき

今回はfilesystemの紹介でした。
生成削除とかは大差ないですが、
フォルダ単位の操作がべらぼうに簡単になってますね。

ただリファレンスチラ見したんですが、
ファイル生成とかはなかったんですよね。
その辺はストリーム使ってやってくださいって感じなのかもしれませんね。

ストリームの件は過去にやりました。
hakase0274.hatenablog.com

filesystem + ストリームでかなり楽にファイルI/Oが使えますね。
それでは今回はこの辺でノシ

参考

nompor.com