用C++语言实现目录文件的非递归遍历并用仿函数来进行文件操作
编程语言:C++
类 别:(实用算法)
主要功能:用C++语言实现目录文件的非递归遍历并用伪函数来进行文件操作
在用进行文件操作时,少不了和目录的递归打交道,但我一般认为.递归算法比较慢.如果可以采用非递归实现,就不要递归.
在非递归算法中,一般我们用一个队列来保存相应的数据.一会列出代码.
还有一个问题,我们递归目录,无非是想对文件进行操作,或者想得到文件的一个列表. 这时,你可以会采用回调函数. 但在我看来,还有更好的实现文案,让"回调"函数是一个对象,就既可以实现回调,也可以保存数据,这就是C++语言的仿函数.今天,我们就用仿函数来对指定的文件进行操作,例如修改文件,或者得到文件列表.
先看一下递归函数的实现:
bool FindPathFiles(LPCTSTR pPath, LPCTSTR pExt, bool includeSubdir,FileOperator* fileOperator]/* = NULL : 这个是仿函数的指针,一会用来对每个文件进行操作 */)
{
WIN32_FIND_DATA fd;
list<tstring> directories; // 这里就是保存递归数据,保存目录
directories.push_back(tstring(pPath));
while(directories.size() > 0)
{
tstring path = directories.front();
directories.pop_front();
tstring pathFind = path + _T("\\*");
HANDLE hFind = NULL;
hFind = ::FindFirstFile(pathFind.c_str(),&fd);
if (hFind == INVALID_HANDLE_VALUE)
{
return false;
}
bool bFinished = false;
while(!bFinished)
{
if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//是目录,如果不是父目录或者当前目录,则把目录压要待处理的目录列表中.
tstring strFileName(fd.cFileName);
if(includeSubdir)
{
if(strFileName != _T(".") && strFileName != _T(".."))
{
directories.push_back(path + _T("\\") + strFileName);
}
}
}
else
{
if(fileOperator)
{
// 目录操作
(*fileOperator)(path, &fd);
}
else
{
wcout << fd.cFileName << endl;
}
}
BOOL bRet = ::FindNextFile(hFind,&fd);
if(!bRet)
{
bFinished = true;
}
}
::FindClose(hFind);
}
return true;
}
上面的部分,着重说明非递归的实现要点,FileOperator* fileOperator,是仿函数的操作
我们再来看一下,如何定义属全上面的仿函数,再写一个抽象基类:
希望大家拍砖讨论
类 别:(实用算法)
主要功能:用C++语言实现目录文件的非递归遍历并用伪函数来进行文件操作
在用进行文件操作时,少不了和目录的递归打交道,但我一般认为.递归算法比较慢.如果可以采用非递归实现,就不要递归.
在非递归算法中,一般我们用一个队列来保存相应的数据.一会列出代码.
还有一个问题,我们递归目录,无非是想对文件进行操作,或者想得到文件的一个列表. 这时,你可以会采用回调函数. 但在我看来,还有更好的实现文案,让"回调"函数是一个对象,就既可以实现回调,也可以保存数据,这就是C++语言的仿函数.今天,我们就用仿函数来对指定的文件进行操作,例如修改文件,或者得到文件列表.
先看一下递归函数的实现:
bool FindPathFiles(LPCTSTR pPath, LPCTSTR pExt, bool includeSubdir,FileOperator* fileOperator]/* = NULL : 这个是仿函数的指针,一会用来对每个文件进行操作 */)
{
WIN32_FIND_DATA fd;
list<tstring> directories; // 这里就是保存递归数据,保存目录
directories.push_back(tstring(pPath));
while(directories.size() > 0)
{
tstring path = directories.front();
directories.pop_front();
tstring pathFind = path + _T("\\*");
HANDLE hFind = NULL;
hFind = ::FindFirstFile(pathFind.c_str(),&fd);
if (hFind == INVALID_HANDLE_VALUE)
{
return false;
}
bool bFinished = false;
while(!bFinished)
{
if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//是目录,如果不是父目录或者当前目录,则把目录压要待处理的目录列表中.
tstring strFileName(fd.cFileName);
if(includeSubdir)
{
if(strFileName != _T(".") && strFileName != _T(".."))
{
directories.push_back(path + _T("\\") + strFileName);
}
}
}
else
{
if(fileOperator)
{
// 目录操作
(*fileOperator)(path, &fd);
}
else
{
wcout << fd.cFileName << endl;
}
}
BOOL bRet = ::FindNextFile(hFind,&fd);
if(!bRet)
{
bFinished = true;
}
}
::FindClose(hFind);
}
return true;
}
我们再来看一下,如何定义属全上面的仿函数,再写一个抽象基类:
class FileOperator
{
public:
virtual void operator()(const tstring& path, LPWIN32_FIND_DATA pfdd) = NULL;
};
如果我们对每个文件进行操作,我们这样来定义,下面一个例子,是我对第个 EXE 文件进行一下修复操作:{
public:
virtual void operator()(const tstring& path, LPWIN32_FIND_DATA pfdd) = NULL;
};
class FixEBOOK : public FileOperator
{
protected:
bool TryFixVirusBook(tstring file)
{
return true;
}
public:
void operator()(const tstring& path, LPWIN32_FIND_DATA pfd)
{
WIN32_FIND_DATA& fd = *pfd;
tstring file(path + _T("\\") + fd.cFileName);
tstring fileExt = file.substr(file.rfind('.'));
transform(fileExt.begin(),fileExt.end(),fileExt.begin(),tolower);
if(fileExt != _T(".exe"))
return;
//操作
this->TryFixVirusBook(file);
return;
}
}
//////////////////////////////////////////////
//声明操作
FixEBOOK oper;
//遍历每个文件,进行操作
FindPathFiles(szCurrentPath,_T(".exe"),true, &oper);
如果我们想得到文件列表,则可以这样写:{
protected:
bool TryFixVirusBook(tstring file)
{
return true;
}
public:
void operator()(const tstring& path, LPWIN32_FIND_DATA pfd)
{
WIN32_FIND_DATA& fd = *pfd;
tstring file(path + _T("\\") + fd.cFileName);
tstring fileExt = file.substr(file.rfind('.'));
transform(fileExt.begin(),fileExt.end(),fileExt.begin(),tolower);
if(fileExt != _T(".exe"))
return;
//操作
this->TryFixVirusBook(file);
return;
}
}
//////////////////////////////////////////////
//声明操作
FixEBOOK oper;
//遍历每个文件,进行操作
FindPathFiles(szCurrentPath,_T(".exe"),true, &oper);
class FileListOper : public FileOperator
{
protected:
list<tstring> m_files;
list<tstring>& GetFiles(void) const
{
return m_files;
}
public:
void operator()(const tstring& path, LPWIN32_FIND_DATA pfd)
{
WIN32_FIND_DATA& fd = *pfd;
tstring file(path + _T("\\") + fd.cFileName);
m_files.push_back(file);
return;
}
}
//////////////////////////////////////////////////////////////////
//声明操作
FileListOper oper;
//遍历每个文件,进行操作
FindPathFiles(szCurrentPath,_T(".exe"),true, &oper);
const list<tstring>& files = oper.GetFiles();
{
protected:
list<tstring> m_files;
list<tstring>& GetFiles(void) const
{
return m_files;
}
public:
void operator()(const tstring& path, LPWIN32_FIND_DATA pfd)
{
WIN32_FIND_DATA& fd = *pfd;
tstring file(path + _T("\\") + fd.cFileName);
m_files.push_back(file);
return;
}
}
//////////////////////////////////////////////////////////////////
//声明操作
FileListOper oper;
//遍历每个文件,进行操作
FindPathFiles(szCurrentPath,_T(".exe"),true, &oper);
const list<tstring>& files = oper.GetFiles();
希望大家拍砖讨论
QQ:273352165
evlon#126.com
转载请注明出处。