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

编程语言:C++
类 别:(实用算法)
主要功能:用C++语言实现目录文件的非递归遍历并用伪函数来进行文件操作

    在用进行文件操作时,少不了和目录的递归打交道,但我一般认为.递归算法比较慢.如果可以采用非递归实现,就不要递归.
   
    在非递归算法中,一般我们用一个队列来保存相应的数据.一会列出代码.
    还有一个问题,我们递归目录,无非是想对文件进行操作,或者想得到文件的一个列表. 这时,你可以会采用回调函数. 但在我看来,还有更好的实现文案,让"回调"函数是一个对象,就既可以实现回调,也可以保存数据,这就是C++语言的仿函数.今天,我们就用仿函数来对指定的文件进行操作,例如修改文件,或者得到文件列表.
   
    先看一下递归函数的实现:
None.gif
ExpandedBlockStart.gifContractedBlock.gif
bool FindPathFiles(LPCTSTR pPath, LPCTSTR pExt, bool includeSubdir,FileOperator* fileOperator]/**//* = NULL : 这个是仿函数的指针,一会用来对每个文件进行操作 */)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gifWIN32_FIND_DATA fd;
InBlock.gif
list<tstring> directories;  // 这里就是保存递归数据,保存目录
InBlock.gif
directories.push_back(tstring(pPath));
InBlock.gif
InBlock.gif
while(directories.size() > 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif  tstring path 
= directories.front();
InBlock.gif  directories.pop_front();
InBlock.gif  tstring pathFind 
= path + _T("\\*");
InBlock.gif  HANDLE hFind 
= NULL;
InBlock.gif  hFind 
= ::FindFirstFile(pathFind.c_str(),&fd);
InBlock.gif  
if (hFind == INVALID_HANDLE_VALUE) 
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif  
return false;
ExpandedSubBlockEnd.gif  }
 
InBlock.gif  
bool bFinished = false;
InBlock.gif  
while(!bFinished)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif  
if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
//是目录,如果不是父目录或者当前目录,则把目录压要待处理的目录列表中.
InBlock.gif
   tstring strFileName(fd.cFileName);
InBlock.gif    
if(includeSubdir)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif    
if(strFileName != _T("."&& strFileName != _T(".."))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      directories.push_back(path 
+ _T("\\"+ strFileName);
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }

InBlock.gif  
else
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
if(fileOperator)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif    
// 目录操作
InBlock.gif
    (*fileOperator)(path, &fd);
ExpandedSubBlockEnd.gif
   }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif    wcout 
<< fd.cFileName << endl;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }

InBlock.gif  BOOL bRet 
= ::FindNextFile(hFind,&fd);
InBlock.gif  
if(!bRet)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    bFinished 
= true;
ExpandedSubBlockEnd.gif  }

ExpandedSubBlockEnd.gif  }

InBlock.gif  ::FindClose(hFind);
ExpandedSubBlockEnd.gif}

InBlock.gif
return true;
ExpandedBlockEnd.gif}

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

    我们再来看一下,如何定义属全上面的仿函数,再写一个抽象基类:
None.gifclass FileOperator
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
public:
InBlock.gif
virtual void operator()(const tstring& path, LPWIN32_FIND_DATA pfdd) = NULL;
ExpandedBlockEnd.gif}
;
None.gif
None.gif
    如果我们对每个文件进行操作,我们这样来定义,下面一个例子,是我对第个 EXE 文件进行一下修复操作:
None.gifclass FixEBOOK : public FileOperator
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
protected:
InBlock.gif
bool TryFixVirusBook(tstring file)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif  
return true;
ExpandedSubBlockEnd.gif}

InBlock.gif
public:
InBlock.gif
void operator()(const tstring& path, LPWIN32_FIND_DATA pfd)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif  WIN32_FIND_DATA
& fd = *pfd;
InBlock.gif  tstring file(path 
+ _T("\\"+ fd.cFileName);
InBlock.gif  tstring fileExt 
= file.substr(file.rfind('.'));
InBlock.gif  transform(fileExt.begin(),fileExt.end(),fileExt.begin(),tolower);
InBlock.gif  
if(fileExt != _T(".exe"))
InBlock.gif  
return;
InBlock.gif  
InBlock.gif  
//操作
InBlock.gif
  this->TryFixVirusBook(file);
InBlock.gif
InBlock.gif  
return;
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**///////////////////////////////////////////////
None.gif//声明操作
None.gif
FixEBOOK oper;
None.gif
//遍历每个文件,进行操作
None.gif
FindPathFiles(szCurrentPath,_T(".exe"),true&oper);
None.gif
None.gif
  如果我们想得到文件列表,则可以这样写:
None.gifclass FileListOper : public FileOperator
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
protected:
InBlock.giflist
<tstring> m_files;
InBlock.giflist
<tstring>& GetFiles(voidconst
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif  
return m_files;
ExpandedSubBlockEnd.gif}

InBlock.gif
public:
InBlock.gif
void operator()(const tstring& path, LPWIN32_FIND_DATA pfd)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif  WIN32_FIND_DATA
& fd = *pfd;
InBlock.gif  tstring file(path 
+ _T("\\"+ fd.cFileName);
InBlock.gif
InBlock.gif  m_files.push_back(file);
InBlock.gif  
return;
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**///////////////////////////////////////////////////////////////////
None.gif//声明操作
None.gif
FileListOper oper;
None.gif
//遍历每个文件,进行操作
None.gif
FindPathFiles(szCurrentPath,_T(".exe"),true&oper);
None.gif
None.gif  
const  list<tstring>& files = oper.GetFiles();
None.gif

    希望大家拍砖讨论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值