C/C++:遍历子目录,枚举文件,FindFirstFile + FindNextFile

来源:互联网 发布:ubuntu查看光纤卡wwn? 编辑:程序博客网 时间:2024/06/06 01:25

转自:http://blog.csdn.net/liigo/article/details/4548577

平时写程序时经常会用到的遍历子目录枚举文件的功能,用 Windows API 函数 FindFirstFile() 和 FindNextFile() 直接实现起来会相当繁琐,有许多细节需要注意和记忆,要在短时间内写出可以正常工作的、没有BUG的、能够递归遍历多层子目录并枚举其中所有文件的程序代码,不是一件轻松的事情。以下这个 doFileEnumeration() 函数,是我(liigo)在 Windows API 函数 FindFirstFile() 和 FindNextFile() 的基础上封装实现的,可以轻松自如的处理遍历子目录枚举文件的任务,使用起来非常简单,具有较高的实用价值。这个函数其实是我之前发布的易语言“辅助调试支持库”(已开源至googlecode)中“枚举文件”“枚举子目录”这两条命令的底层实现函数。

  doFileEnumeration() 函数功能是实现枚举文件和枚举子目录,支持递归处理多层子目录嵌套的情况。它有五个参数:第一个参数lpPath指定欲遍历的路径(文件夹);第二个参数bRecursion指定是否递归处理子目录;第三个参数bEnumFiles指定是枚举文件还是枚举子目录;第四个参数pFunc为用户回调函数,枚举过程中每遇到一个文件或子目录,都会调用它,并传入这个文件或子目录的完整路径;第五个参数pUserData为用户任意指定的数据,它也将被传入用户回调函数。用户回调函数(EnumerateFunc)有两个参数,一个是文件或子目录的完整路径(lpFileOrPath),一个是用户自定义数据(pUserData),它被自动调用,用户需在此函数中编码处理代码。

  这个函数经过我(liigo)的仔细设计,接口很简洁,使用也方便。有意去除了 FindFirstFile(Ex)/FindNextFile 中过滤文件名称或属性的部分功能,也是出于简化接口的考虑,——在用户回调函数中处理这些事情也是很容易的(在易语言中更容易)。在实现的细节上,重点是对子目录和递归的处理。以下是完整的源代码:

 

[cpp] view plaincopy
  1. #include <windows.h>  
  2.   
  3. typedef BOOL (WINAPI *EnumerateFunc) (LPCSTR lpFileOrPath, void* pUserData);  
  4.   
  5. void doFileEnumeration(LPSTR lpPath, BOOL bRecursion, BOOL bEnumFiles, EnumerateFunc pFunc, void* pUserData)  
  6. {  
  7.   
  8.     static BOOL s_bUserBreak = FALSE;  
  9.     try{  
  10.         //-------------------------------------------------------------------------  
  11.         if(s_bUserBreak) return;  
  12.           
  13.         int len = strlen(lpPath);  
  14.         if(lpPath==NULL || len<=0) return;  
  15.           
  16.         //NotifySys(NRS_DO_EVENTS, 0,0);  
  17.           
  18.         char path[MAX_PATH];  
  19.         strcpy(path, lpPath);  
  20.         if(lpPath[len-1] != '//') strcat(path, "//");  
  21.         strcat(path, "*");  
  22.           
  23.         WIN32_FIND_DATA fd;  
  24.         HANDLE hFindFile = FindFirstFile(path, &fd);  
  25.         if(hFindFile == INVALID_HANDLE_VALUE)  
  26.         {  
  27.             ::FindClose(hFindFile); return;  
  28.         }  
  29.           
  30.         char tempPath[MAX_PATH]; BOOL bUserReture=TRUE; BOOL bIsDirectory;  
  31.           
  32.         BOOL bFinish = FALSE;  
  33.         while(!bFinish)  
  34.         {  
  35.             strcpy(tempPath, lpPath);  
  36.             if(lpPath[len-1] != '//') strcat(tempPath, "//");  
  37.             strcat(tempPath, fd.cFileName);  
  38.               
  39.             bIsDirectory = ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);  
  40.               
  41.             //如果是.或..  
  42.             if( bIsDirectory  
  43.                 && (strcmp(fd.cFileName, ".")==0 || strcmp(fd.cFileName, "..")==0))   
  44.             {         
  45.                 bFinish = (FindNextFile(hFindFile, &fd) == FALSE);  
  46.                 continue;  
  47.             }  
  48.               
  49.             if(pFunc && bEnumFiles!=bIsDirectory)  
  50.             {  
  51.                 bUserReture = pFunc(tempPath, pUserData);  
  52.                 if(bUserReture==FALSE)  
  53.                 {  
  54.                     s_bUserBreak = TRUE; ::FindClose(hFindFile); return;  
  55.                 }  
  56.             }  
  57.               
  58.             //NotifySys(NRS_DO_EVENTS, 0,0);  
  59.               
  60.             if(bIsDirectory && bRecursion) //是子目录  
  61.             {  
  62.                 doFileEnumeration(tempPath, bRecursion, bEnumFiles, pFunc, pUserData);  
  63.             }  
  64.               
  65.             bFinish = (FindNextFile(hFindFile, &fd) == FALSE);  
  66.         }  
  67.           
  68.         ::FindClose(hFindFile);  
  69.           
  70.         //-------------------------------------------------------------------------  
  71.     }catch(...){ ASSERT(0); return; }  
  72. }  

 

以下是应用示例代码:incopy

  1. BOOL WINAPI myEnumerateFunc(LPCSTR lpFileOrPath, void* pUserData)  
  2. {  
  3.     char* pdot;  
  4.     if((pdot = strrchr(lpFileOrPath, '.')) && stricmp(pdot, ".mp3") == 0)  
  5.     {  
  6.         printf("%s/n", lpFileOrPath);  
  7.     }  
  8.     return TRUE;  
  9. }  
  10.   
  11. int main()  
  12. {  
  13.     doFileEnumeration("C://Music", TRUE, TRUE, myEnumerateFunc, NULL);  
  14.     return 0;  
  15. }

  16. 用一下代码比较容易看懂:

void BrowseCurrentDir(CString strDir) {CFileFind finder;CString strPath;CString strName;if (strDir.Right(1) != _T("\\")) {strDir += _T("\\");}strDir += _T("*.*");BOOL bWorking = finder.FindFile(strDir);while (bWorking) {bWorking = finder.FindNextFile();if (finder.IsDots()) {continue;}if (finder.IsDirectory()) {strPath = finder.GetFilePath();//strName = finder.GetFileName();//ODS(strPath);BrowseCurrentDir(strPath); //递归调用} else {strPath = finder.GetFilePath();strName = finder.GetFileName();//ODS(strPath);//ODS(_T("fileName: ") + strName);}}finder.Close();}


0 0
原创粉丝点击