FindFirstFile ファイルの検索

Cの宣言:

HANDLE FindFirstFile(LPCTSTR FileName, LPWIN32_FIND_DATA FindData);

VBの宣言:

Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" ( _
	ByVal FileName As String, _
	ByRef FindData As WIN32_FIND_DATA) As Long

説明:

FileNameで指定された検索文字列に一致するパス名を持つファイルまたはディレクトリの検索を開始する。ワイルドカードの指定も可能である。

検索結果の情報はFindDataに格納される。また、返されたハンドルをFindNextFileに渡すことにより、検索を継続することができる。

NTでは、"\\?\"によるMAX_PATH以上の長さのファイル名の指定が可能である。

FindFirstFile関数は、短い形式のファイル名と長い形式のファイル名の両方のファイル名をFileNameと一致するかどうか調べる。一つのファイルの名前が両方の形式で一致する場合でも、検索結果として得られるのは一つである。

FindFirstFileやFindNextFileでのファイル検索を終了する場合、FindCloseFileを実行する。

引数の意味は、以下の通り。
FileName (IN) 検索文字列。ワイルドカードの指定が可能である。
FindData (OUT) 検索結果が返されるバッファ。

戻り値は、検索を継続するためにFindNextFileに渡すハンドルである。検索文字列と一致するファイルが一つも見つからない場合や、エラーが発生した場合、INVALID_HANDLE_VALUEが返される。

Cのサンプル:

/* My Documents配下のファイルを全て検索する */
void DoFind()
{
	HANDLE hFind;
	WIN32_FIND_DATA fd;
	FILETIME ft;
	SYSTEMTIME st;

	/* 最初のファイル検索 */
	hFind = FindFirstFile("\\my documents\\*.*", &fd);

	/* 検索失敗? */
	if(hFind == INVALID_HANDLE_VALUE) {
		printf("検索失敗\n");
		return; /******** エラー終了 ********/
	}

	do {
		/* 更新時間取得 */
		FileTimeToLocalFileTime(&fd.ftLastWriteTime, &ft);
		FileTimeToSystemTime(&ft, &st);

		/* 結果の表示 */
		printf("ファイル名: %s", fd.cFileName);

		if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
			printf("(ディレクトリ)");
		}

		printf("\n短いファイル名: %s\n", fd.cAlternateFileName);
		printf("ファイルサイズ: %d\n", fd.nFileSizeLow);
		printf("更新日: %04d/%02d/%02d %02d:%02d:%02d\n\n",
			st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);

	} while(FindNextFile(hFind, &fd)); '次のファイルを検索

	/* 検索終了 */
	FindClose(hFind);
}

VBのサンプル:

'主な宣言
Public Type SYSTEMTIME
	Year As Integer
	Month As Integer
	DayOfWeek As Integer
	Day As Integer
	Hour As Integer
	Minute As Integer
	Second As Integer
	Milliseconds As Integer
End Type

Public Type FILETIME
	DateTimeLow As Long
	DateTimeHigh As Long
End Type

Public Type WIN32_FIND_DATA
	Attributes As Long
	CreationTime As FILETIME
	AccessTime As FILETIME
	WriteTime As FILETIME
	FileSizeHigh As Long
	FileSizeLow As Long
	Reserved0 As Long
	Reserved1 As Long
	 FileName As String * MAX_PATH
	ShortFileName As String * 14
End Type

'My Documents配下のファイルを全て検索する
Private Sub DoFind()

	Dim hFind As Long
	Dim FindData As WIN32_FIND_DATA
	Dim FTime As FILETIME
	Dim STime As SYSTEMTIME
	Dim Msg As String
	Dim bResult As Long

	'最初のファイル検索
	hFind = FindFirstFile("\my documents\*.*", FindData)

	'検索失敗か?
	If hFind = INVALID_HANDLE_VALUE Then
		MsgBox "検索失敗"
		Exit Sub   '******** エラー終了 ********
	End If

	Do
		'ファイル更新日を時分秒形式に変換
		FileTimeToLocalFileTime FindData.WriteTime, FTime
		FileTimeToSystemTime FTime, STime

		'検索結果のメッセージ作成
		With FindData
			Msg = "検索結果:" & vbCr

			'NULL文字を取り除く
			.FileName = Left(.FileName, InStr(.FileName, vbNullChar) - 1)
			.ShortFileName = Left(.ShortFileName, InStr(.ShortFileName, vbNullChar) - 1)

			'検索結果のファイル名
			Msg = Msg & "ファイル名:" & Trim(.FileName)
			    
			'ディレクトリかどうか
			If (.Attributes And FILE_ATTRIBUTE_DIRECTORY) <> 0 Then
				Msg = Msg & "(ディレクトリ)"
			End If

			'短いファイル名
			Msg = Msg & vbCr & "短いファイル名:" & Trim(.ShortFileName) & vbCr

			'ファイルサイズ(下位32bit)
			Msg = Msg & "サイズ:" & .FileSizeLow & vbCr

			'更新日
			With STime
				Msg = Msg & "更新日:" & .Year & "/" & .Month & "/" & .Day
				Msg = Msg & " " & .Hour & ":" & .Minute & ":" & .Second
			End With
		End With

		'検索結果表示
		MsgBox Msg

		'次を検索
		bResult = FindNextFile(hFind, FindData)

	Loop While bResult <> 0

	'検索の終了
	FindClose hFind

End Sub

短い形式のファイル名から長い形式のファイル名を取得するVBのサンプル:

Private Sub GetLongPathName()

	Dim hFind As Long
	Dim FindData As WIN32_FIND_DATA
	Dim ShortFileName As String
	Dim Idx As Integer
	Dim NextDelim As Integer
	Dim InsSep As String
	Dim LongFileName As String
	Dim Token As String

	ShortFileName = "c:\MYDOCU~1\012345~1\ABCDEF~1.TXT" 'can't root dir
	Idx = 1

	ShortFileName = Trim(ShortFileName)
	If Left(ShortFileName, 1) <> "\" Then
		ShortFileName = ShortFileName + "\" '番人
	End If

	If Left(ShortFileName, 2) = "\\" Then
		Idx = Idx + 2
		If Mid(ShortFileName, Idx, 1) = "?" Then
			MsgBox "error"
			Exit Sub
		End If

		Idx = InStr(Idx, ShortFileName, "\") + 1
	End If

	    
	If Mid(ShortFileName, Idx + 1, 1) = ":" Then Idx = Idx + 2
	If Mid(ShortFileName, Idx, 1) = "\" Then Idx = Idx + 1

	LongFileName = Left(ShortFileName, Idx - 1)

	NextDelim = InStr(Idx, ShortFileName, "\")

	Do
		Token = Mid(ShortFileName, Idx, NextDelim - Idx + 1)
		If Token = ".\" Or Token = "..\" Then
			FindData.FileName = Left(Token, Len(Token) - 1)
		Else
			hFind = FindFirstFile(Left(ShortFileName, NextDelim - 1), FindData)
			If hFind = INVALID_HANDLE_VALUE Then
				MsgBox "error"
				Exit Sub
			End If

			FindClose hFind

			With FindData
				.FileName = Left(.FileName, InStr(.FileName, vbNullChar) - 1)
			End With
		End If

		LongFileName = LongFileName & InsSep & Trim(FindData.FileName)

		InsSep = "\"

		Idx = NextDelim + 1
		NextDelim = InStr(NextDelim + 1, ShortFileName, "\")
	Loop Until NextDelim = 0

	MsgBox LongFileName

End Sub


(original text:1998/12/25 更新)

本ドキュメントの内容は保証しません。本ドキュメントによって生じた結果について、一切の責任を負いません。