C++でのファイル再帰検索

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
DAICHI0922
記事: 26
登録日時: 6年前

C++でのファイル再帰検索

#1

投稿記事 by DAICHI0922 » 6年前

C++でファイル検索のプログラムを組んでいるのですが、上手く動作してくれません。
FindFirstFileとNextFileの再帰を使っているのですが、全く動作しません。

開発環境はVisualStudio2017です。

コード:

#include<Windows.h>
#include<iostream>
#include<string>
#include<fstream>

using namespace std;

string current = "C:\\Users\\";
char szDirectoryName[MAX_PATH];

int FindFile(string current);

int main() {
FindFile(current);
return 0;
}

int FindFile(string current) {
ofstream ofs("FileName.txt",ios::app);
WIN32_FIND_DATA date;
HANDLE handle = FindFirstFile(current.c_str(), &date);
if (handle == INVALID_HANDLE_VALUE)cout << "ファイルなし(FindFirstFile)\n" << endl;
else {
for (;;) {
if ((strcmp(date.cFileName, ".") != 0) && (strcmp(date.cFileName, "..") != 0)) {
if (date.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
GetCurrentDirectory(sizeof(szDirectoryName) / sizeof(szDirectoryName[0]), szDirectoryName);
cout << "(DirectryName)" << szDirectoryName << endl;
current = current + "\\" + date.cFileName;
cout << "(current)" << current << endl;
FindFile(current);
}
else {
cout << "(FileName)" << date.cFileName << endl;
ofs << date.cFileName << endl;
}
}
if (!FindNextFile(handle, &date)) {
if (GetLastError() == ERROR_NO_MORE_FILES) {
cout << "ファイルなし(FindNextFile)\n" << endl;
break;
}
break;
}
}
}
FindClose(handle);
ofs.close();
return 0;
}

かずま

Re: C++でのファイル再帰検索

#2

投稿記事 by かずま » 6年前

コードを左詰めで書いて、よくそれでプログラムが読めますね。
インデント(字下げ)するのは、プログラムの構造を明確にするためです。

コード:

#include <Windows.h>
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

string current = "C:\\Users\\";
char szDirectoryName[MAX_PATH];

int FindFile(string current);

int main()
{
	FindFile(current);
	return 0;
}

int FindFile(string current)
{
	ofstream ofs("FileName.txt", ios::app);
	WIN32_FIND_DATA date;
	HANDLE handle = FindFirstFile(current.c_str(), &date);
	if (handle == INVALID_HANDLE_VALUE)
		cout << "ファイルなし(FindFirstFile)\n" << endl;
	else {
		for (;;) {
			if ((strcmp(date.cFileName, ".") != 0)
					&& (strcmp(date.cFileName, "..") != 0)) {
				if (date.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
					GetCurrentDirectory(MAX_PATH, szDirectoryName);
					cout << "(DirectryName)" << szDirectoryName << endl;
					current = current + "\\" + date.cFileName;
					cout << "(current)" << current << endl;
					FindFile(current);
				} else {
					cout << "(FileName)" << date.cFileName << endl;
					ofs << date.cFileName << endl;
				}
			}
			if (!FindNextFile(handle, &date)) {
				if (GetLastError() == ERROR_NO_MORE_FILES) {
					cout << "ファイルなし(FindNextFile)\n" << endl;
					break;
				}
				break;
			}
		}
	}
	FindClose(handle);
	ofs.close();
	return 0;
}
if文や、forループがどこで始まってどこで終わっているのかがよくわかるでしょう。

次に ofstream を再帰関数の中にこんな風に書くと、おかしなことが起こります。
FindFile関数内の ofsオブジェクトは別々のものなので、バッファリングの
バッファもそれぞれが持っています。
例えば次のプログラムを試してみてください。

コード:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
	ofstream ofs1("abc.txt", ios::app);
	ofs1 << "abc\n";
	ofstream ofs2("abc.txt", ios::app);
	ofs2 << "def\n";
	ofstream ofs3("abc.txt", ios::app);
	ofs3 << "ghi\n";
	ofs3.close();
	ofs2.close();
	ofs1.close();
}
実行結果の abc.txt

コード:

ghi
def
abc
ofs3.close() で "ghi\n" が出力された後に、
"def\n" や "abc\n" が追加されています。

元のプログラムの ofs はグローバルオブジェクトにするか、
あるいは、main のローカルオブジェクトにして、FindFile には
その参照を渡すようにしないといけないでしょう。

FindFirstFileをよく読んでください。
"C:\\Users\\" も "C:\\Users" もダメで、"C:\\Users\\*" としないと
ディレクトリの中のファイルは取得できないでしょう。

次のコードを参考に、もう一度挑戦してみてください。

コード:

#include <windows.h> // FindFirstFile, FindNextFile
#include <iostream>  // cout
#include <string>    // string

using namespace std;

int FindFile(string dir)
{
	static string dot("."), dotdot("..");
	WIN32_FIND_DATA data;
	HANDLE handle = FindFirstFile((dir + "\\*").c_str(), &data);
	if (handle == INVALID_HANDLE_VALUE)
		cout << "FindFirstFile failed\n";
	else {
		do {
			if (data.cFileName != dot && data.cFileName != dotdot) {
				string path = dir + "\\" + data.cFileName; 
				if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
					FindFile(path);
				else
					cout << path << endl;
			}
		} while (FindNextFile(handle, &data));
		FindClose(handle);
	}
	return 0;
}

int main()
{
	FindFile("C:\\tmp\\java");
	return 0;
}

返信

“C言語何でも質問掲示板” へ戻る