- FindFirstFile
- FindNextFile
- FindClose
以下のヘッダファイル【enumerate_files.hpp】で機能を提供しています。
#pragma once
#include <windows.h>
#include <string>
/**
* ファイルを探索する
* @author a5ua
* @tparam Callback ファイルが見つかったときに呼ばれる関数
* @param path 探索を開始するディレクトリのパス
* @param callback callback(path, find_data);という形で呼ばれる。<br>
* pathはファイルが存在するディレクトリのパス、find_dataは見つかったファイルの情報
*/
template <typename Callback>
void enumerate_files(LPCWSTR path, Callback callback)
{
HANDLE find_handle; // ファイル探索用ハンドル
WIN32_FIND_DATAW find_data; // 探索情報
// 探索するためのワイルドカードを設定
std::wstring file_name(path);
file_name += L"*.*";
// 探索開始
find_handle = FindFirstFileW(file_name.c_str(), &find_data);
// ファイルが見つからなかったら終了
if (find_handle == INVALID_HANDLE_VALUE) {
return;
}
// ファイルが見つからなくなるまで繰り返し
do {
// 見つかったファイルに対する処理
callback(path, find_data);
} while (FindNextFileW(find_handle, &find_data));
// 探索終了
FindClose(find_handle);
}
ファイルが見つかったときに、どのような処理をするかは、全てcallbackに投げているので、
この関数の実装自体はシンプルになっています。
ただし、この関数は単体では動作しないので、適切にコールバック関数をつくってやる必要があります。
以下に、コールバックのサンプルとともに、enumerate_filesの使い方を示します。
#include <tchar.h>
#include <windows.h>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include "enumerate_files.hpp"
/* コールバック用の関数オブジェクトのサンプル */
// ディレクトリを再帰的に探索して、ファイルパスのリストを作成する
class sample_callback
{
public:
// ファイルリストの格納先
sample_callback(std::vector<std::wstring> &files) : m_files(files)
{
}
void operator()(LPCWSTR path, const WIN32_FIND_DATAW &find_data)
{
std::wstring name = find_data.cFileName; // 見つけたファイル名
// カレントディレクトリと親ディレクトリは無視
if (name != L"." && name != L"..") {
// 探索パスとファイル名から、見つけたファイルへのパスを作る
std::wstring new_path(path);
new_path += name;
if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// 見つけたファイルがディレクトリなら、再帰的に探索
new_path += L"\\";
enumerate_files(new_path.c_str(), sample_callback(m_files));
} else {
// ファイルパスを追加
m_files.push_back(new_path);
}
}
}
private:
std::vector<std::wstring> &m_files;
};
/* enumerate_files の使い方サンプル */
int main()
{
// 日本語が表示できるように
std::wcout.imbue(std::locale("japanese"));
const LPCWSTR path = L".\\"; // カレントディレクトリ以下を探索
std::vector<std::wstring> v; // ファイル名格納先
// ファイルを列挙
enumerate_files(path, sample_callback(v));
// ファイル名表示
std::copy(v.begin(), v.end(), std::ostream_iterator<std::wstring, wchar_t>(std::wcout, L"\n"));
}
- 再帰的に走査しない
- *.cppファイルのみを列挙する