はかせのラボ

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

C++ フォルダ配下のファイルの一括読み込み①

あいさつ

どうも、はかせです。
最近ゲームで取り扱うファイルが増えてきて管理が大変になってきました。
なのでフォルダから一括読み込みをしたいと思います。
今回はフォルダ配下のファイルパスの取得までやります。

使用API

ファイルのパス取得には、
Win32APIのFindFirstFileFindNextFileFindCloseを使います。
それぞれざっくり説明
FindFirstFile・・・ファイル名を指定し探す
FindNextFile・・・同ディレクトリ内の次のファイルを探す
FindClose・・・開いたものを閉じる

また私のプログラムでは主にwchar_tを使っていますがこれらで取れるのはcharなので変換します。
色々ありますが今回はstd::wsting_convertを使って
string->wstringで変換したいと思います。

実装

今回は次のファイルを読み込んでみます。
f:id:hakase0274:20181211233738p:plain
コードです。

#include "DirFileLoder.h"
#include <Windows.h>
#include <vector>
#include <string>
#include <iostream>
#include <locale> 
#include <codecvt> 
#include <cstdio>
#include <stdexcept>

std::vector<std::wstring> DirFileLoder::GetFilePathInDir(const std::string& dir_name, const std::string& extension) noexcept(false)
{
	HANDLE hFind;
	//defined at Windwos.h
	WIN32_FIND_DATA win32fd;
	//ファイル名の配列
	std::vector<std::wstring> file_names;

	//探すファイル名指定 ワイルドカードを使用
	std::string search_name = dir_name + "\\*." + extension;
	//ファイル検索
	hFind = FindFirstFile(search_name.c_str(), &win32fd);

	//見つからなかったか
	if (hFind == INVALID_HANDLE_VALUE) 
	{
		throw std::runtime_error("file not found");
	}

	//次のファイルがある限り読み込み続ける
	do 
	{
		//ディレクトリなら無視
		if (win32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {}
		else 
		{
			//ファイル名をパス付で取得
			std::string fileName = win32fd.cFileName;
			fileName.insert(0, "Texture/");
			//string->wstringに変換
			std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cv;
			std::wstring ws = cv.from_bytes(fileName);
			file_names.push_back(ws);
			//取得したパスを表示
			printf("%ls\n", file_names.back().c_str());
		}
	} while (FindNextFile(hFind, &win32fd));
	//閉じる
	FindClose(hFind);

	return file_names;
}

/*以下使い方*/

#if _DEBUG
#include <crtdbg.h>
#endif

#include "Main.h"

int main()
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	//読み込みクラス
	auto loder = new DirFileLoder();
	//ディレクトリと拡張子
	string dir = _T("Texture");
	string extention = _T("png");
	//読み込み
	auto files = loder->GetFilePathInDir(dir, extention);
	//不要なので削除
	delete loder;
	getchar();
}

まずは動作テストということでコンソールアプリケーションでやってます。
次に実行結果です。
f:id:hakase0274:20181211233758p:plain
しっかりパスを取得できてます。

あとがき

今回はフォルダの一括読み込み①でした。
次回はこれを本プロジェクトに組み込んで画像を一括読み込みします。

それでは今回はこの辺でノシ