ページ 11

ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月15日(土) 21:45
by あかり
ディレクトリ内のすべてのファイル名を取得したいのですが、どうすればいいかわかりません。
考えはvectorでstring型を確保して、ディレクトリ内のファイル名もしくは、フルパスを取得したいと思っています。
よろしくお願いします。

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月15日(土) 22:17
by みけCAT
使用する言語とOSを教えてください。

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月15日(土) 22:20
by あかり
OS windows8 64
言語 C++
環境 Visual Studio 2013
です、よろしくお願いします。

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月15日(土) 22:51
by softya(ソフト屋)
その環境だとWindowsAPIが定番ではないでしょうか。

「Win32API(C言語)編 第54章 ファイルを列挙する」
http://www.geocities.jp/ky_webid/win32c/054.html

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月15日(土) 23:19
by あかり
教えていただいたURLから必要な部分だけ取り出してみたのですが、

コード:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

int main(void){
	HANDLE hSearch, hFile;
	WIN32_FIND_DATA fd;
	DWORD writeSize;
	TCHAR filename[MAX_PATH + 10];

		// ファイルを新規作成
	hFile = CreateFile(
		_T("filelist.txt"), GENERIC_WRITE, 0, NULL,
		CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
		);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		return 0;
	}
			// 全てのファイルを列挙する
	hSearch = FindFirstFile(_T("D:/*.*"), &fd);
	if (hSearch == INVALID_HANDLE_VALUE)
	{
		return 0;
	}
	while (TRUE)
	{
		// 列挙されたファイル名を書き出す
		_tcscpy(filename, fd.cFileName); // ファイル名をバッファにコピー
		_tcscat(filename, _T("\r\n"));   // 末尾に改行文字を加える
		WriteFile(
			hFile, filename, (DWORD)(_tcslen(filename)*sizeof(TCHAR)),
			&writeSize, NULL
			);

		if (!FindNextFile(hSearch, &fd))
		{
			if (GetLastError() == ERROR_NO_MORE_FILES) 
				break;
			else 
				break;
		}
	}

	FindClose(hSearch);
	CloseHandle(hFile);

	return 0;
}

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月15日(土) 23:23
by あかり
すいません、途中で送信してしまいました。
ソースなんですが、
_tcscpy(filename, fd.cFileName); // ファイル名をバッファにコピー
のところをstring型へ送るようにすればいいと思うのですが、
WIN32_FIND_DATAのデータをstring型にコピーするにはどうすればいいですか?

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月15日(土) 23:33
by a5ua
Visual Studio 2013なら<filesystem>を使うのがお手軽だと思います。

コード:

#include <iostream>
#include <vector>
#include <string>
#include <filesystem>

int main()
{
	std::vector<std::string> file_list;

	// カレントディレクトリ以下のファイル名を取得する
	// 再帰的にファイル名を取得する場合は、std::tr2::sys::recursive_directory_iteratorを使う
	for (std::tr2::sys::directory_iterator it("."), end; it != end; ++it) {
		file_list.push_back(it->path());
	}

	// 取得したファイル名をすべて表示する
	for (auto &path : file_list) {
		std::cout << path << std::endl;
	}
}

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月15日(土) 23:38
by みけCAT
あかり さんが書きました:_tcscpy(filename, fd.cFileName); // ファイル名をバッファにコピー
のところをstring型へ送るようにすればいいと思うのですが、
WIN32_FIND_DATAのデータをstring型にコピーするにはどうすればいいですか?
std::string型はcharの配列で表現された文字列を代入するという表記が使えるので、ファイル名だけなら素直に

コード:

std::string filename_string;
filename_string=fd.cFileName;
でいいと思います。
WIN32_FIND_DATAのデータ全てをstd::string型にしたいなら、sprintfなどで文字列に変換する必要があります。
std::stringではなく、自作または他のライブラリのstring型なら、それに合った方法で変換すればいいと思います。

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月15日(土) 23:40
by softya(ソフト屋)
<filesystem>はC++11のライブラリですね。
それが使えるなら、それで良いと思います。

ただ、charやwchar_tからstringへの代入変換もC++を使う以上は覚えたほうが良いと思いますよ。
と書いていたらみけCATさんが例を書いてましたね。

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月16日(日) 00:09
by あかり
皆さん、返信ありがとうございます。
filesystemを使った、ソースを使ってみようと思います。
それとなんですが、
みけCAT さんが書きました:
あかり さんが書きました:_tcscpy(filename, fd.cFileName); // ファイル名をバッファにコピー
のところをstring型へ送るようにすればいいと思うのですが、
WIN32_FIND_DATAのデータをstring型にコピーするにはどうすればいいですか?
std::string型はcharの配列で表現された文字列を代入するという表記が使えるので、ファイル名だけなら素直に

コード:

std::string filename_string;
filename_string=fd.cFileName;
でいいと思います。
WIN32_FIND_DATAのデータ全てをstd::string型にしたいなら、sprintfなどで文字列に変換する必要があります。
std::stringではなく、自作または他のライブラリのstring型なら、それに合った方法で変換すればいいと思います。
であったstring型なんですが、私も試してはみたのですが、ビルドエラーが起きていて使うことが出来ません。

エラー 1 error C2679: 二項演算子 '=' : 型 'WCHAR [260]' の右オペランドを扱う演算子が見つかりません (または変換できません)。

と表示されています。
a5uaさんのソースで解決はしたのですが、ここをどうすればいいか教えてもらえませんか?

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月16日(日) 00:14
by h2so5
文字セットをUnicodeからマルチバイトに変えてください。

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月16日(日) 00:18
by softya(ソフト屋)
文字コードセットがUNICODEになっているので、WCHARマクロ=wchar_t型でコンパイルされている様です。
この場合は、char文字セットのstd::stringではなく、std::wstringを使います。
※ ただしTCHARで決め打ちは良くないのですがマイクロソフトがtstringを作っていないので困ったものです。

こうして解決する方法もあります。
「その14 UNICODEで分けないtstring型を宣言する」
http://marupeke296.com/TIPS_No14_tstring.html

文字コードに関しては勉強されることをおすすめします。

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月16日(日) 00:23
by あかり
文字コードでコンパイルされるのも変わるんですね、ありがとうございます。
皆さんのおかげで解決しました、ありがとうございました!

Re: ディレクトリ内のすべてのファイル名を取得する

Posted: 2014年2月16日(日) 00:42
by softya(ソフト屋)
あかり さんが書きました:文字コードでコンパイルされるのも変わるんですね、ありがとうございます。
皆さんのおかげで解決しました、ありがとうございました!
TCHAR系はマイクロソフト独自の変則仕様である事をお断りしておきます。
gccなど他のコンパイラでは通用しないので覚えておいて下さいね。
例えばLinuxやAndroid NDKで使うとひどい目に合います。