C++函数学习之文件遍历小函数的设计实例


之前写过 关于 win32 下磁盘的遍历方法,下面是将里面实现的磁盘遍历函数重新设计了一下,因为磁盘遍历,文件夹遍历在很多时候还是很常见的,为了不修改遍历的函数体,我将处理文件的部分交由一个回调函数去处理,这样的话,你甚至可以把下面的代码写在dll里面,需要进行文件遍历的地方,只要实现一个回调函数传进去就可以了。

  函数声明:
  // 函数 : ScanDirectory
  // 功能 : 遍历一个目录,传入一个函数指针
  // 返回值 : BOOL
  // 参数 : const TCHAR *pszPath 传入路径
  // 参数 : LPSCANDISK_START_ROUTINE lpFunAddress 函数指针回调指针
  // 参数 : PVOID lpParam 回调函数参数
  // 参数 : BOOL bIsRecur/* = TRUE*/ 是否递归
  // 附注 : 回调函数原型 DWORD WINAPI ScanProc(TCHAR *pFilePath, LPVOID lpParameter);
  // 回调函数的第一个参数是扫描到一个文件的全名typedef DWORD (WINAPI *LPSCANDISK_START_ROUTINE)(TCHAR *pFilePath, LPVOID lpParameter);
  BOOL ScanDirectory
  (const TCHAR *pszPath, LPSCANDISK_START_ROUTINE lpFunAddress, PVOID lpParam, BOOL bIsRecur = TRUE) 函数实现: // 函数 : ScanDirectory
  // 功能 : 遍历一个目录,传入一个函数指针
  // 返回值 : BOOL
  // 参数 : const TCHAR *pszPath 传入路径
  // 参数 : LPSCANDISK_START_ROUTINE lpFunAddress 函数指针回调指针
  // 参数 : PVOID lpParam 回调函数参数
  // 参数 : BOOL bIsRecur/* = TRUE*/ 是否递归
  // 附注 : 回调函数原型 DWORD WINAPI ScanProc(TCHAR *pFilePath, LPVOID lpParameter);
  // 回调函数的第一个参数是扫描到一个文件的全名
  BOOL ScanDirectory(const TCHAR *pszPath, LPSCANDISK_START_ROUTINE lpFunAddress, PVOID lpParam, BOOL bIsRecur/* = TRUE*/)
  {
  BOOL bRet = FALSE;
  TCHAR *s = NULL;
  HANDLE hFind = NULL;
  WIN32_FIND_DATA fd = {0};
  TCHAR szFileName[MAX_PATH] = TEXT("");
  ::lstrcpy(szFileName, pszPath);
  s = szFileName + ::lstrlen(szFileName);
  if (*(s-1) != TEXT(’\\’))
  *s++ = TEXT(’\\’);
  ::lstrcpy(s, TEXT("*.*"));
  hFind = FindFirstFile(szFileName, &fd);
  if (hFind == INVALID_HANDLE_VALUE)
  goto Exit0;
  do
  {
  // 过滤
  if (::lstrcmpi(TEXT("."), fd.cFileName) == 0 || ::lstrcmpi(TEXT(".."), fd.cFileName) == 0)
  continue;
  ::lstrcpy(s, fd.cFileName);
  *(s + ::lstrlen(fd.cFileName)) = L’\0’;
  // 如果是文件夹则递归
  if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && bIsRecur)
  {
  ScanDirectory(szFileName, lpFunAddress, lpParam, bIsRecur);
  }
  else
  {
  // 对文件进行处理
  if (lpFunAddress)
  lpFunAddress(szFileName, lpParam);
  }
  }while(::FindNextFile(hFind, &fd));
  bRet = TRUE;  
  Exit0:
  if( hFind != INVALID_HANDLE_VALUE )
  {
  ::FindClose( hFind );
  hFind = NULL;
  }
  return bRet;
  }


  不过这样的实现有个小缺陷,文件特别多的话,效率会比较低,因为每一个文件都调用了一次回调函数,其实接口还可以设计一个过滤器出来,让扫描函数只对我们感兴趣的文件进行回调,考试,大提示再就是文件夹的处理,也可以进行回调,具体怎么做大家也可以练练手

相关内容