#1 はじめに
大量の画像をOpenCVで画像処理するときに、フォルダ以下にあるファイル一覧を取得したかったので、その関数を作成しました。
(2019/1/18 追記)
コメントで教えて頂いたfilesystemを使う方法も追記しました。
#2 WinAPIを使う
参考サイト[1]を参照して作成しました。C++17以降が使用できる環境であれば、後述しているfilesystemを使う方法がおすすめです。
#2.1 ソースコード
FileNames.cpp
/**
* @brief フォルダ以下のファイル一覧を取得する関数
* @param[in] folderPath フォルダパス
* @param[out] file_names ファイル名一覧
* return true:成功, false:失敗
**/
bool getFileNames(std::string folderPath, std::vector<std::string> &file_names)
{
HANDLE hFind;
WIN32_FIND_DATA win32fd;
std::string search_name = folderPath + "\\*";
hFind = FindFirstFile(search_name.c_str(), &win32fd);
if (hFind == INVALID_HANDLE_VALUE) {
throw std::runtime_error("file not found");
return false;
}
/* 指定のディレクトリ以下のファイル名をファイルがなくなるまで取得する */
do {
if (win32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
/* ディレクトリの場合は何もしない */
printf("directory\n");
}
else {
/* ファイルが見つかったらVector配列に保存する */
file_names.push_back(win32fd.cFileName);
printf("%s\n", file_names.back().c_str());
}
} while (FindNextFile(hFind, &win32fd));
FindClose(hFind);
return true;
}
#3 filesystemを使う
C++17で標準入りしたfilesystemを使う方法を書きました。こちらの方法では絶対パスが得られます。
Visual Studio 2017でC++17を使う方法は参考サイト[2]を参照してください。
#3.1 ソースコード
FileNames.cpp
/**
* @brief フォルダ以下のファイル一覧を取得する関数
* @param[in] folderPath フォルダパス
* @param[out] file_names ファイル名一覧
* return true:成功, false:失敗
*/
bool getFileNames(std::string folderPath, std::vector<std::string> &file_names)
{
using namespace std::filesystem;
directory_iterator iter(folderPath), end;
std::error_code err;
for (; iter != end && !err; iter.increment(err)) {
const directory_entry entry = *iter;
file_names.push_back( entry.path().string() );
printf("%s\n", file_names.back().c_str());
}
/* エラー処理 */
if (err) {
std::cout << err.value() << std::endl;
std::cout << err.message() << std::endl;
return false;
}
return true;
}
#3.2 出力結果
vector配列にフォルダ以下にあるファイルの絶対パスが格納されます。サブフォルダは格納されません。
#4 参考サイト
[1] http://d.hatena.ne.jp/s-kita/20100129/1264776052
[2] https://codezine.jp/article/detail/10890