载入中,请稍候……

C++实现目录文件的非递归遍历并用伪函数来进行文件操作

Admin 于 2008-10-22 00:53:21 发表C/C++

订阅: http://www.miniboke.com/Feed/Article_79.aspx
引用: http://www.miniboke.com/Trackback/TVzehezEvTCWzTGtIPck.aspx (UTF-8)
UTF8ToBytes < C++实现目录文件的非递归遍历并用伪函数来进行文件操作 > 在JPG图片中追加、分离其它文件数据的脚本

在用进行文件操作时,少不了和目录的递归打交道,但我一般认为.递归算法比较慢.如果可以采用非递归实现,就不要递归.

在非递归算法中,一般我们用一个队列来保存相应的数据.一会列出代码.
还有一个问题,我们递归目录,无非是想对文件进行操作,或者想得到文件的一个列表. 这时,你可以会采用回调函数. 但在我看来,还有更好的实现文案,让"回调"函数是一个对象,就既可以实现回调,也可以保存数据,这就是C++语言的仿函数.今天,我们就用仿函数来对指定的文件进行操作,例如修改文件,或者得到文件列表.
先看一下递归函数的实现:

  1. bool FindPathFiles(LPCTSTR pPath, LPCTSTR pExt, bool includeSubdir,FileOperator* fileOperator]/**//* = NULL : 这个是仿函数的指针,一会用来对每个文件进行操作 */
  2. WIN32_FIND_DATA fd; 
  3. list<tstring> directories;  // 这里就是保存递归数据,保存目录 
  4. directories.push_back(tstring(pPath)); 
  5.  
  6. while(directories.size() > 0) 
  7.   tstring path = directories.front(); 
  8.   directories.pop_front(); 
  9.   tstring pathFind = path + _T("\\*"); 
  10.   HANDLE hFind = NULL; 
  11.   hFind = ::FindFirstFile(pathFind.c_str(),&fd); 
  12.   if (hFind == INVALID_HANDLE_VALUE)  
  13.   { 
  14.   return false
  15.   }  
  16.   bool bFinished = false
  17.   while(!bFinished) 
  18.   { 
  19.   if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
  20.   { 
  21.     //是目录,如果不是父目录或者当前目录,则把目录压要待处理的目录列表中. 
  22.    tstring strFileName(fd.cFileName); 
  23.     if(includeSubdir) 
  24.     { 
  25.     if(strFileName != _T(".") && strFileName != _T("..")) 
  26.     { 
  27.       directories.push_back(path + _T("\\") + strFileName); 
  28.     } 
  29.     } 
  30.   } 
  31.   else 
  32.   { 
  33.     if(fileOperator) 
  34.     { 
  35.     // 目录操作 
  36.     (*fileOperator)(path, &fd); 
  37.    } 
  38.     else 
  39.     { 
  40.     wcout << fd.cFileName << endl; 
  41.     } 
  42.   } 
  43.   BOOL bRet = ::FindNextFile(hFind,&fd); 
  44.   if(!bRet) 
  45.   { 
  46.     bFinished = true
  47.   } 
  48.   } 
  49.   ::FindClose(hFind); 
  50. return true

上面的部分,着重说明非递归的实现要点,FileOperator* fileOperator,是仿函数的操作

我们再来看一下,如何定义属全上面的仿函数,再写一个抽象基类:

  1. class FileOperator 
  2. public
  3. virtual void operator()(const tstring& path, LPWIN32_FIND_DATA pfdd) = NULL; 
  4. }; 

如果我们对每个文件进行操作,我们这样来定义,下面一个例子,是我对第个 EXE 文件进行一下修复操作:

  1. class FixEBOOK : public FileOperator 
  2. protected
  3. bool TryFixVirusBook(tstring file) 
  4.   return true
  5. public
  6. void operator()(const tstring& path, LPWIN32_FIND_DATA pfd) 
  7.   WIN32_FIND_DATA& fd = *pfd; 
  8.   tstring file(path + _T("\\") + fd.cFileName); 
  9.   tstring fileExt = file.substr(file.rfind('.')); 
  10.   transform(fileExt.begin(),fileExt.end(),fileExt.begin(),tolower); 
  11.   if(fileExt != _T(".exe")) 
  12.   return
  13.    
  14.   //操作 
  15.   this->TryFixVirusBook(file); 
  16.  
  17.   return
  18.  
  19. /**/////////////////////////////////////////////// 
  20. //声明操作 
  21. FixEBOOK oper; 
  22. //遍历每个文件,进行操作 
  23. FindPathFiles(szCurrentPath,_T(".exe"),true, &oper); 
  24.  
  25.   如果我们想得到文件列表,则可以这样写: 
  26. class FileListOper : public FileOperator 
  27. protected
  28. list<tstring> m_files; 
  29. list<tstring>& GetFiles(voidconst 
  30.   return m_files; 
  31. public
  32. void operator()(const tstring& path, LPWIN32_FIND_DATA pfd) 
  33.   WIN32_FIND_DATA& fd = *pfd; 
  34.   tstring file(path + _T("\\") + fd.cFileName); 
  35.  
  36.   m_files.push_back(file); 
  37.   return
  38.  
  39. /**/////////////////////////////////////////////////////////////////// 
  40. //声明操作 
  41. FileListOper oper; 
  42. //遍历每个文件,进行操作 
  43. FindPathFiles(szCurrentPath,_T(".exe"),true, &oper); 
  44.  
  45.   const  list<tstring>& files = oper.GetFiles(); 

 

被阅842次, 0投一票
  • 看完了要说点啥么?
  • 昵称 (不填说不了话)
  • 信箱地址 (不会被公开,但是不填也说不了话)
  • 网址 (这个不填也成)

Powered by MiniBoke v2.0.0.8 Build 0828

Copyright © 2008 迷你博客. All rights reserved.

粤ICP备07500939号