山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他フォルダー内のファイル名をサブフォルダーも含めて検索する
概要
FindFirstFile APIとFindNextFile APIを用いてフォルダー内のファイル名をサブフォルダーの中も含めて検索するプログラムである。
E:¥testフォルダーについてdirコマンドによる表示結果と本プログラムの表示結果を以下に示す。
本プログラムの実行結果 | dir E:¥test /b /s |
---|---|
E:¥test¥findfile1 E:¥test¥findfile1.sdf E:¥test¥findfile1.sln E:¥test¥Release E:¥test¥findfile1¥Debug E:¥test¥findfile1¥findfile1.cpp E:¥test¥findfile1¥findfile1.vcxproj E:¥test¥findfile1¥findfile1.vcxproj.filters E:¥test¥findfile1¥Release E:¥test¥findfile1¥x64 E:¥test¥findfile1¥Debug¥findfile1.obj E:¥test¥findfile1¥Debug¥vc120.idb E:¥test¥findfile1¥Debug¥vc120.pdb E:¥test¥findfile1¥Release¥findfile1.obj E:¥test¥findfile1¥Release¥vc120.pdb E:¥test¥findfile1¥x64¥Debug E:¥test¥findfile1¥x64¥Debug¥findfile1.obj E:¥test¥findfile1¥x64¥Debug¥vc120.idb E:¥test¥findfile1¥x64¥Debug¥vc120.pdb E:¥test¥Release¥findfile1.exe E:¥test¥Release¥findfile1.pdb |
E:¥test¥findfile1 <DIR> E:¥test¥findfile1¥Debug <DIR> E:¥test¥findfile1¥Debug¥findfile1.obj E:¥test¥findfile1¥Debug¥vc120.idb E:¥test¥findfile1¥Debug¥vc120.pdb E:¥test¥findfile1¥Release <DIR> E:¥test¥findfile1¥Release¥findfile1.obj E:¥test¥findfile1¥Release¥vc120.pdb E:¥test¥findfile1¥x64 <DIR> E:¥test¥findfile1¥x64¥Debug <DIR> E:¥test¥findfile1¥x64¥Debug¥findfile1.obj E:¥test¥findfile1¥x64¥Debug¥vc120.idb E:¥test¥findfile1¥x64¥Debug¥vc120.pdb E:¥test¥findfile1¥findfile1.cpp E:¥test¥findfile1¥findfile1.vcxproj E:¥test¥findfile1¥findfile1.vcxproj.filters E:¥test¥Release <DIR> E:¥test¥Release¥findfile1.exe E:¥test¥Release¥findfile1.pdb E:¥test¥findfile1.sdf E:¥test¥findfile1.sln |
テスト環境
コンパイラ
Visual C++ 2008 Standard 32/64bitVisual C++ 2013 Express 32/64bit
プロジェクトの作成
Win32コンソールアプリケーション実行環境
Windows 8.1 Enterprise 64bitWindows 7 EnterPrise Service Pack 1 64bit
Windows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit
プログラムソースの概要
_tmain関数
_tsetlocale関数によりUNICODE文字を標準出力に正しく表示させるためにロケールを設定します。FindFile関数が検索するパス名とワイルカードをFileFindParam構造体のメンバーに設定してからFindFile関数を呼び出します。
FindFile
フォルダ名の検索のワイルカードは*.*、ファイル名の検索には引数で指定されたワイルカードを用いるため、最初にフォルダー名を検索し、次にファイル名の検索を行います。フォルダー名が見つかった場合は、FindFileを再帰呼び出しを行います。
フォルダー名・ファイル名のフルパス名は階層が深くなると長くなることが予測できます。
文字数の最大値は、ANSI版のAPIはMAX_PATHマクロで定義される260文字、UNICODE版のAPIではパスの前に¥¥?¥を前置することにより最大32,000ワイド文字なので、検索時のパス名を保存するために最大文字数分のバッファを確保します。
フォルダー名およびファイル名の検索は基本的に以下の似通ったものです。
FindFirstFile APIで検索条件を指定し最初の1個目のフォルダー・ファイルの情報を取得します。
戻り値は検索ハンドルです。
戻り値がINVALID_HANDLE_VALUEの場合は、ファイルが見つからないことを示しています。
検索されたファイル名に関する情報はFindFileData構造体に格納されます。
FindFileData構造体メンバーは以下の通りです。
DWORD dwFileAttributes; // 属性
FILETIME ftCreateTime; // 作成日時
FILETIME ftLastAccessTime; // 最終アクセス日時
FILETIME ftLastWriteTime; // 最終更新日時
DWORD nFileSizeHigh; // ファイルサイズ(上位32ビット)
DWORD nFileSizeLow; // ファイルサイズ(下位32ビット)
TCHAR cFileName[MAX_PATH]; // ファイル名
TCHAR cAlternateFileName[14]; // 8.3形式のファイル
メンバーdwFileAttributesはファイルの属性を示しておりFILE_ATTRIBUTE_DIRECTORY定数とのAND演算を実行し結果が0でなければフォルダー、0の場合はファイルを示します。フォルダーを検索しているときは、ファイル属性をチェックしフォルダーの時、検索パスとフォルダー名を結合しフルパスを作成し、フォルダー名を表示後、末尾に¥を付加し、FindFileを呼び出しサブフォルダーを検索します。
ファイルを検索しているときは、ファイル属性をチェックしファイルのとき、ファイル名を表示します。 次のフォルダー名・ファイル名を検索するためには、FindNextFile APIを用います。戻り値が0の場合は、ファイルが見つからないことを示しているのでフォルダー名・ファイル名の検索を終了させます。
検索が終了したらFindCloseにより検索ハンドルを解放します。 FileFindParam構造体のfull_passメンバーが現在の検索されたフルパス名、lenメンバーがフルパスの文字数、levelメンバーが現在検索しているサブフォルダーの階層数、max_pathメンバーがfull_passメンバーの要素の最大数を示します。
プログラムソース
// フォルダー内のファイル名をサブフォルダーも含めて検索する
// Visual C++ 2013 32/64bit
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#ifdef UNICODE
#define MAX_PATH_EX 32000
#else
#define MAX_PATH_EX MAX_PATH
#endif
struct FileFindParam{
TCHAR* pass; // 検索対象となるフォルダー名を指定
TCHAR* card; // ワイルカード
int max_path; // パス名の最大長
int len; // full_passの長さを保存
int level; // 現在の階層数
TCHAR* full_pass; // フルパスを保存
FileFindParam(int max){
max_path = max;
level=len = 0;
full_pass = new TCHAR[max_path];
}
~FileFindParam(){
delete []full_pass;
}
};
// フォルダー内のファイル名をサブフォルダーも含めて検索する
void FindFile(FileFindParam* file_find_param);
void _tmain(void){
// UNICODE文字を標準出力に正しく表示させるためにロケールを設定
_tsetlocale(LC_ALL, _TEXT(""));
FileFindParam param(MAX_PATH_EX);
param.pass = _TEXT("E:¥¥test¥¥");
param.card = _TEXT("*.*");
FindFile(¶m);
}
void FindFile(FileFindParam* p){
if (p->len == 0){
p->len = _tcslen(p->pass);
_tcscpy_s(p->full_pass, p->max_path, p->pass);
}
int parent_len = p->len;
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
_tcscpy_s(p->full_pass + p->len, p->max_path - p->len, _TEXT("*.*"));
hFind = FindFirstFile(p->full_pass, &FindFileData); // フォルダーの検索
if (hFind != INVALID_HANDLE_VALUE){
do{
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
if (_tcscmp(FindFileData.cFileName, TEXT("..")) && _tcscmp(FindFileData.cFileName, TEXT("."))){ // 親ディレクトリは無視する
_tcscpy_s(p->full_pass + p->len, p->max_path - p->len, FindFileData.cFileName);
_tprintf(_TEXT("%s¥t<DIR>¥n"), p->full_pass);
p->len = p->len + _tcslen(FindFileData.cFileName);
p->full_pass[p->len] = _T('¥¥');
p->full_pass[p->len + 1] = _T('¥0');
++p->len;
++ p->level;
FindFile(p); // サブフォルダーの検索
-- p->level;
p->len = parent_len;
}
}
} while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
}else
return;
_tcscpy_s(p->full_pass + p->len, p->max_path - p->len, p->card);
hFind = FindFirstFile(p->full_pass, &FindFileData); // ファイル名の検索
if (hFind != INVALID_HANDLE_VALUE){
do{
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0){
_tcscpy_s(p->full_pass + p->len, p->max_path - p->len, FindFileData.cFileName);
_putts(p->full_pass);
}
} while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
}
}
ソースファイルのダウンロード
Copyright (C) 2012 山本ワールド All Rights Reserved.