Windows API中,有一组专门的函数和结构,用于遍历目录,它们是FindFirstFile函数、FindNextFile函数和WIN32_FIND_DATA结构。使用FindFirstFile和FindNextFile函数并与do-while循环结合,可以完成遍历目录的任务。
值得一提的是,FindFirstFile输入参数的路径需使用通配符,也就是用户可以根据一些条件来对查找的文件作简单的过滤。下面实例讲解查找特定目录下的所有文件和文件夹。读者可根据自己的需要,指定查找文件的条件。
(1)FindFirstFile。
查找第一个目录或文件,获取查找句柄
◇参数
lpFileName:输入参数,查找的目录,需使用通配符指定查找的文件目标。
lpFindFileData:输出参数,指向WIN32_FIND_DATA结构的指针,为找到的文件及其若干属性信息。
◇返回值
返回HANDLE值,如果执行失败,返回1NVALID HANDLE VALUE,如果成功则返回查找句柄。
◇使用说明
如果查找文件需在循环中与FindNextFile配合使用,FindNextFile需要用到FindFirstFile返回的句柄
(2)FindNextFile
对文件、文件夹进行循环查找,
◇参数
hFindFile:输入参数,查找句柄,由FindFirstFile返回。
lpFindFileData:输出参数,指向WIN32_FIND_DATA结构的指针,为找到的文件及其若干属性信息。
◇返回值
返回BOOL值,表示是否成功。
◇使用说明
需循环查找。
WIN32_FIND_DATA结构用于表示找到的文件,结构中包括文件、目录的名字,创建、最后访问和最后写入时间,文件大小、文件属性等。
>>>本实例实现了对指定目录中文件和子目录的遍历,并将遍历得到的文件和其他属性打印到界面上。
1 #include <Windows.h> 2 #include <stdio.h> 3 4 DWORD EnumerateFileInDrectory(LPSTR szPath) 5 { 6 WIN32_FIND_DATA FindFileData; 7 HANDLE hListFile; 8 CHAR szFilePath[MAX_PATH]; 9 10 //构造代表子目录和文件夹路径的字符串,使用通配符“*” 11 lstrcpyA(szFilePath,szPath); 12 13 //注释的代码可用于查找所有以".txt"结尾的文件 14 //lstrcatA(szFilePath,"\\*.txt"); 15 lstrcatA(szFilePath,"\\*"); 16 hListFile=FindFirstFile(szFilePath,&FindFileData); 17 //判断句柄 18 if(hListFile==INVALID_HANDLE_VALUE) 19 { 20 printf("错误: %d\n",GetLastError()); 21 return 1; 22 } 23 else 24 { 25 do 26 { 27 /*如果不想显示代表本级目录和上级目录的"."和"..", 28 可以使用注释部分的代码过滤 29 if(lstrcmp(FindFileData.cFileName,TEXT("."))==0 || 30 lstrcmp(FindFileData.cFileName,TEXT(".."))==0) 31 { 32 continue; 33 } 34 */ 35 //打印文件名、目录名 36 printf("%s\t\t",FindFileData.cFileName); 37 //判断文件属性,是否为加密文件或文件夹 38 if(FindFileData.dwFileAttributes && FILE_ATTRIBUTE_ENCRYPTED) 39 { 40 printf("<加密> "); 41 } 42 //判断文件属性,是否为隐藏文件或文件夹 43 if(FindFileData.dwFileAttributes && FILE_ATTRIBUTE_HIDDEN) 44 { 45 printf("<隐藏> "); 46 } 47 //判断文件属性,是否为目录 48 if(FindFileData.dwFileAttributes && FILE_ATTRIBUTE_DIRECTORY) 49 { 50 printf("<DIR> "); 51 } 52 //根据文件属性表中的内容自行添加、判断文件属性 53 printf("\n"); 54 }while(FindNextFile(hListFile,&FindFileData)); 55 } 56 return 0; 57 } 58 int main(int argc,PCHAR argv[]) 59 { 60 if(argc==2) 61 { 62 EnumerateFileInDrectory(argv[1]); 63 } 64 else 65 { 66 CHAR szCurrentPath[MAX_PATH]; 67 GetCurrentDirectoryA(MAX_PATH,szCurrentPath); 68 EnumerateFileInDrectory(szCurrentPath); 69 } 70 return 0; 71 }
>>>在上个实例的基础上稍加改造,进行循环递归调用,采用树形结构深度遍历的方法。可以遍历指定目录中的所有文件、包括子目录中的文件。
1 #include <windows.h> 2 #include <stdio.h> 3 4 /* 预处理申明 */ 5 #pragma comment (lib, "User32.lib") 6 7 /* 全局变量 */ 8 //记录所有的文件和目录数 9 DWORD dwTotalFileNum = 0; 10 11 /* ************************************ 12 * DWORD ListAllFileInDrectory(LPSTR szPath) 13 * 功能 遍历目录及所有子目录,打印路径 14 * 参数 LPTSTR szPath,为需遍历的目录 15 * 返回值 0代表执行完成,1代码发生错误 16 **************************************/ 17 DWORD ListAllFileInDrectory(LPSTR szPath) 18 { 19 CHAR szFilePath[MAX_PATH]; 20 21 WIN32_FIND_DATA FindFileData; 22 HANDLE hListFile; 23 CHAR szFullPath[MAX_PATH]; 24 25 //构造代表子目录和文件夹路径的字符串,使用通配符“*” 26 lstrcpyA(szFilePath, szPath); 27 lstrcatA(szFilePath, "\\*"); 28 //查找第一个文件/目录,获得查找句柄 29 hListFile = FindFirstFile(szFilePath,&FindFileData); 30 31 if(hListFile==INVALID_HANDLE_VALUE) 32 { 33 printf("错误:%d",GetLastError()); 34 return 1; 35 } 36 else 37 { 38 do 39 { 40 // 过滤“.”和“..”,不需要遍历 41 if(lstrcmp(FindFileData.cFileName,TEXT("."))==0|| 42 lstrcmp(FindFileData.cFileName,TEXT(".."))==0) 43 { 44 continue; 45 } 46 //构造成全路径 47 wsprintfA(szFullPath,"%s\\%s", 48 szPath,FindFileData.cFileName); 49 dwTotalFileNum++; 50 //打印 51 printf("\n%d\t%s\t",dwTotalFileNum,szFullPath); 52 53 //如果是目录,则递归调用,列举下级目录 54 if(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) 55 { 56 printf("<DIR>"); 57 ListAllFileInDrectory(szFullPath); 58 } 59 } 60 while(FindNextFile(hListFile, &FindFileData)); 61 } 62 return 0; 63 } 64 int main(int argc, PCHAR argv[]) 65 { 66 if(argc == 2)//如果有直接调用 67 { 68 ListAllFileInDrectory(argv[1]); 69 } 70 else//如果没有输入就默认为exe所在处 71 { 72 CHAR szCurrentPath[MAX_PATH]; 73 GetCurrentDirectory(MAX_PATH,szCurrentPath); 74 ListAllFileInDrectory(szCurrentPath); 75 } 76 return 0; 77 }