一直没有找到单步文件查找方式的代码,所以研究了一下,希望能给大家节省些时间。
一个人的精力是有限的,我不可能完成所有的应用所需的类,如果大家有觉得写的比较好比较完善的类,可以发给我(最好是在VC6下可编译),请注明是否可以发表,如果可以发表我会注明作者,加入代码库系列,如果有需求的也可以给我写信或留言,我会根据情况在适当的时候添加到代码库,谢谢大家的支持.
我的EMAIL : lgtest@sina.com
代码并没有经过严格的测试,希望大家能给挑挑错,大家支持是我的动力!.
////////////////////////////////////////////////////H////////////////////////////////////////////////////////////
#ifndef LGLIB_FINDFILE_H
#define LGLIB_FINDFILE_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <string>
#include <deque>
using namespace std;
namespace lglib
{
enum FindType
{
Find_ERR = -0x0001,
Find_End = 0x0000,
Find_Dot = 0x0001,
Find_Directory = 0x0002,
Find_Directory_Close = 0x0004,
Find_File = 0x0008,
Find_NULL = 0x0010
};
typedef BOOL (* OW_DEF_FUNC )(string findedfile,FindType type,const WIN32_FIND_DATA Data);
//Q:为什么不用递归?
//A:由于递归方式在目录层次较深的情况,会发生堆栈溢出情况,而且对资源的消耗也的确比较大
//Q:为什么写成单步调用?
//A:由于某些时候,你可能不需要在很短时间内将文件全部搜索完.
//比如,将一定目录的超过一定时间的文件删除
//这个任务可能没有那么紧迫,完全可以慢条斯理的解决,并给其他线程留出更多的时间
//不使用递归搜索文件,就要自己实现一个先进后出的堆栈
//not use recursion to search file ,actually to realize a stack of own
//根据堆栈的内容进行搜索,本类不支持多线程操作,如果一定要支持,请自行修改
//base on the content of stack to search,this
//this class not support multithread,if u want's to support ,please modify yourself.
//Create by 龙仪 at 2005-5-29
class lg_FindFile
{
public:
lg_FindFile();
virtual ~lg_FindFile();
//get the SearchPath that u Assign at The Init Function
//for example this can be use when FileFind return a Find_ERR
//and u call this function to tell user witch directory not exist
string GetSearchDir() const;
//u must call this function once before u call FileFind Function
BOOL Init(string FilePath,string FileExt);
//Find DestFile(include a Directory) function
//The process Function to process the result as u want
//if The process Function return FALSE this function would break
//Param type to assign the type you want's to process
FindType FileFind(OW_DEF_FUNC process,int32 type);
//reuse this class on new path and fileExt
//after call this function u must call Init to set path and fileExt
void Clear();
private:
//this function just run one step
FindType FindOnStep(string& OutString,WIN32_FIND_DATA& Data);
// compare the end of n byte between two string witch no case
// if same return true, or return false
BOOL CompareNoCase(string S1,string S2,size_t n);
//if the path is a directory would call this function
FindType AddDirectory(string path,string & OutString);
//struct backup in DequeList
struct FilePacket{
string CurPath;
HANDLE hFile;
};
//Directory will be Search
string m_FilePath;
//file extention will be search
string m_FileExt;
//flag of Init
BOOL m_bIsInited;
protected:
//deque list of struct FilePacket
deque<FilePacket> DequeList;
};
}
#endif // LGLIB_FINDFILE_H
////////////////////////////////////////////CPP///////////////////////////////////////////////////////////
#include "stdafx.h"
#include "filemon.h"
#include "lg_FindFile.h"
#include "lg_Exception.h"
#include <winbase.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
namespace lglib
{
lg_FindFile::lg_FindFile() : m_bIsInited(FALSE)
{
}
lg_FindFile::~lg_FindFile()
{
Clear();
}
void lg_FindFile::Clear()
{
m_bIsInited = FALSE;
int Size = DequeList.size();
for(int i = 0;i < Size;i++)
{
FindClose(DequeList.front().hFile);
DequeList.pop_front();
}
//DequeList.empty();
Size = DequeList.size();
}
string lg_FindFile::GetSearchDir() const
{
if(!m_bIsInited)
throw lg_Exception("lg_FindFile::GetSearchDir()","Not Been Inited",0x00000002);
return m_FilePath;
}
BOOL lg_FindFile::Init(string FilePath,string FileExt)
{
if(m_bIsInited)
return FALSE;
m_FilePath = FilePath;
m_FileExt = FileExt;
m_bIsInited = TRUE;
return TRUE;
}
FindType lg_FindFile::AddDirectory(string path,string &OutString)
{
WIN32_FIND_DATA FindData;
FilePacket pack;
string Temp = path;
pack.CurPath = path;
int Pos = Temp.rfind('\\');
if((Pos + 1) != Temp.size() ){
Temp += "\\*.*";
pack.CurPath += "\\";
}else{
Temp += "*.*";
}
pack.hFile = FindFirstFile(Temp.c_str(), &FindData);
if(pack.hFile == INVALID_HANDLE_VALUE)
return Find_ERR;
DequeList.push_front(pack);
OutString = pack.CurPath;
return Find_Directory;
}
//比较字符串后n位是否相同,忽略大小写
BOOL lg_FindFile::CompareNoCase(string S1,string S2,size_t n)
{
if(S1.size() < n || S2.size() < n)
return FALSE;
for(int i = 1 ;i< n + 1;i++)
{
if(toupper(S1[S1.size() - i]) != toupper(S2[S2.size() - i]))
return FALSE;
}
return TRUE;
}
//单步查找文件
FindType lg_FindFile::FindOnStep(string& OutString,WIN32_FIND_DATA& Data)
{
if(!m_bIsInited)
throw lg_Exception("lg_FindFile::FindOnStep","Not Been Inited",0x00000001);
WIN32_FIND_DATA FindData;
if(DequeList.size() == 0)
{
return AddDirectory(m_FilePath,OutString);
}else{
FilePacket pack;
pack = DequeList.front();
BOOL Ret = FindNextFile(pack.hFile, &FindData);
if(!Ret)
{
FindClose(pack.hFile);
OutString = pack.CurPath;
DequeList.pop_front();
if(DequeList.size() == 0)
return Find_End;
else
return Find_Directory_Close;
}
if(strcmp(FindData.cFileName, ".") && strcmp(FindData.cFileName, "..") )
{
string PathTemp=pack.CurPath;
PathTemp+=FindData.cFileName;
if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
return AddDirectory(PathTemp,OutString);
}
else
{
//比较扩展名是否相同
if(CompareNoCase(m_FileExt,"*.*",3)||CompareNoCase(PathTemp,m_FileExt,m_FileExt.size()-1))
{
OutString = PathTemp;
Data = FindData;
return Find_File;
}
// if(CompareNoCase(PathTemp,m_FileExt,m_FileExt.size()-1))
// {
// OutString = PathTemp;
// return Find_File;
// }
}
}else{
return Find_Dot;
}
}
return Find_NULL;
}
//查找给定的类型
FindType lg_FindFile::FileFind(OW_DEF_FUNC process,int32 type)
{
FindType Val = Find_NULL;
string Temp;
WIN32_FIND_DATA Data;
while((Val = FindOnStep(Temp,Data))>Find_End){
if(Val & type){
if(!process(Temp,Val,Data))
break;
}
}
return Val;
}
}
///////////////////////HOW TO USE///////////////////////////
定义lg_FindFile m_FindFile;
m_FindFile.Init("d:\\查找目录","*.jpg");
BOOL MyProcess(string SrcFileName,FindType type,const WIN32_FIND_DATA Data)
{
static int32 Counter = 0;
switch(type)
{
case Find_Directory:
LGTRACE(Output_Console,"查找目录%s",SrcFileName.c_str());
break;
case Find_Directory_Close:
LGTRACE(Output_Console,"关闭目录%s",SrcFileName.c_str());
break;
case Find_File:
CTime t = CTime(Data.ftCreationTime);
LGTRACE(Output_Console,"创建时间%s",t.Format("%Y年%m月%d日%H时%M分%S秒"));
LGTRACE(Output_Console,"%s-%ld",SrcFileName.c_str(),++Counter);
break;
}
return FALSE;
}
void CFileMonDlg::OnSearch()
{
FindType Val = m_FindFile.FileFind(MyProcess,Find_File|Find_Directory_Close|Find_Directory);
if(Val == Find_ERR)
{
LGTRACE(Output_Console,"目录[%s]不存在",m_FindFile.GetSearchDir().c_str());
}
//继续查找其他目录的其他类型文件
m_FindFile.Clear();
m_FindFile.Init("d:\\TESTTEST","*.jpgt");
m_FindFile.FileFind(MyProcess,Find_File);
.....
}