SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

Visual C++ 2017で一足お先にfilesystem

  • このエントリーをはてなブックマークに追加

 Visual Studio 2017がリリースされました、Visual Studio 20周年おめでとうございます。早速RC版からupdateし、変更点の確認ついでに目新しいヘッダが追加されてはいないかとsystem-includeディレクトリを眺めていたら<filesystem>が目に留まりました。filesystemはVC++2015にも入ってたんですが、紹介するのをコロッと忘れてましたよ。ファイルとディレクトリの操作にとっても便利なfilesystemを紹介いたします。

  • このエントリーをはてなブックマークに追加

filesystemの概要

 filesystemはBoostに収録されたライブラリ:boost.filesystemをベースとし、今年末までには決まるはずの標準規格:C++17の一部となる予定。まだ仕様が確定していないので、Visual C++ 2015/2017に見つけたfilesystemは実験的(experimental)な実装であり、クラスや関数は名前空間:std::experimental::filesystemに置かれています。

 filesystemのイケてるところをお見せするため、「カレント・ディレクトリ配下のファイル/ディレクトリを再帰的に列挙する」コードを書きました。

 まずはWin32-API版。

list-01n walk_dir_recursive_win32.cpp
#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を使うと:

list-02 walk_dir_recursive_filesystem.cpp
#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版と同じ結果が得られます。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
パス文字列の操作

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/10076 2017/05/16 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング