FindFirstFile
基本概述:
FindFirstFile是Windows API中用于启动一次文件 / 目录搜索的函数。它会在指定路径下查找第一个匹配条件的文件或目录,并返回一个搜索句柄(用于后续的FindNextFile调用),同时通过结构体返回该文件 / 目录的详细信息。
FindFirstFile 是一个宏,根据项目是否定义UNICODE宏,会映射到宽字符版本(FindFirstFileW)或ANSI版本(FindFirstFileA)。
基本语法
1 2 3 4 5 6 7 8 9
| HANDLE FindFirstFileW( [in] LPCWSTR lpFileName, [out] LPWIN32_FIND_DATAW lpFindFileData );
HANDLE FindFirstFileA( [in] LPCSTR lpFileName, [out] LPWIN32_FIND_DATAA lpFindFileData );
|
lpFileName
表示要搜索的文件或目录路径,支持通配符*和?:
*:匹配任意长度的字符序列(如*.txt匹配所有后缀为.txt的文件)。
?:匹配单个字符(如file?.doc匹配file1.doc、fileA.doc等)。
路径格式:可以是绝对路径(如L"C:\\Users\\test\\*.pdf")或相对路径(如L".\\images\\*.*",.表示当前目录)。
LPWIN32_FIND_DATAW
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| typedef struct _WIN32_FIND_DATAW { DWORD dwFileAttributes; FILETIME ftCreationTime; FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; DWORD nFileSizeHigh; DWORD nFileSizeLow; DWORD dwReserved0; DWORD dwReserved1; _Field_z_ WCHAR cFileName[ MAX_PATH ]; _Field_z_ WCHAR cAlternateFileName[ 14 ]; } WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW;
typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; } FILETIME, *PFILETIME, *LPFILETIME; FILETIME 本质是通过两个 32 位 DWORD 成员组合成一个 64 位整数 来表示时间。
|
WIN32_FIND_DATAW是文件搜索中 “信息载体” 的核心,通过其成员可获取文件的几乎所有基础属性:
判断类型(文件 / 目录)→ 用dwFileAttributes。
获取文件名 → 用cFileName。
处理文件大小 → 组合nFileSizeHigh和nFileSizeLow。
跟踪文件变更 → 用ftLastWriteTime
返回值
成功:返回一个非零的搜索句柄(HANDLE类型),该句柄需传递给后续的FindNextFile使用。
失败:返回INVALID_HANDLE_VALUE(宏定义为 -1),需通过GetLastError()获取具体错误原因,常见错误:
ERROR_FILE_NOT_FOUND:未找到任何匹配的文件 / 目录。
ERROR_ACCESS_DENIED:无权限访问指定路径。
ERROR_PATH_NOT_FOUND:路径不存在。
FindNextFile
继续执行对 FindFirstFile、FindFirstFileEx或 FindFirstFileTransacted 函数的上一次调用的文件搜索。
基本语法
1 2 3 4 5 6 7 8 9
| BOOL FindNextFileW( [in] HANDLE hFindFile, [out] LPWIN32_FIND_DATAW lpFindFileData );
BOOL FindNextFileA( [in] HANDLE hFindFile, [out] LPWIN32_FIND_DATAA lpFindFileData );
|
基本示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| #include <Windows.h> #include <stdio.h>
void PrintFileAttributes(DWORD attributes) { printf("属性: "); if (attributes & FILE_ATTRIBUTE_DIRECTORY) printf("目录 | "); if (attributes & FILE_ATTRIBUTE_READONLY) printf("只读 | "); if (attributes & FILE_ATTRIBUTE_HIDDEN) printf("隐藏 | "); if (attributes & FILE_ATTRIBUTE_SYSTEM) printf("系统 | "); if (attributes & FILE_ATTRIBUTE_ARCHIVE) printf("归档"); printf("\n"); }
int main() { LPCWSTR searchPath = L".\\*";
WIN32_FIND_DATAW findData; ZeroMemory(&findData, sizeof(WIN32_FIND_DATAW));
HANDLE hFind = FindFirstFileW(searchPath, &findData); if (hFind == INVALID_HANDLE_VALUE) { printf("搜索失败!错误码: %d\n", GetLastError()); return 1; }
printf("开始遍历目录: .\\\n"); printf("========================================\n");
do { if (wcscmp(findData.cFileName, L".") == 0 || wcscmp(findData.cFileName, L"..") == 0) { continue; }
wprintf(L"名称: %s\n", findData.cFileName);
PrintFileAttributes(findData.dwFileAttributes);
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { LONGLONG fileSize = (LONGLONG)findData.nFileSizeHigh << 32 | findData.nFileSizeLow; printf("大小: %lld 字节\n", fileSize); }
printf("----------------------------------------\n");
} while (FindNextFileW(hFind, &findData));
DWORD lastError = GetLastError(); if (lastError != ERROR_NO_MORE_FILES) { printf("遍历过程出错!错误码: %d\n", lastError); } else { printf("遍历完成,无更多文件。\n"); }
FindClose(hFind);
return 0; }
|