📄 rapidfinder.cpp
字号:
// RapidFinder.cpp: implementation of the CRapidFinder class.
//
/*===================================================================
作者:Kelvin U.V
时间:2002-9-15
功能:多线程文件查找
版本:1.0
/===================================================================*/
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RapidFinder.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
const int CRapidFinder::HIGHEST_PRIORITY=2;
const int CRapidFinder::ABOVE_NORMAL=1;
const int CRapidFinder::NORMAL_PRIORITY=0;
const int CRapidFinder::BELOW_NORMAL=-1;
const int CRapidFinder::LOWEST_PRIORITY=-2;
const LPCTSTR ErrMsg[]={
{"未指定查找路径!"},
{"程序结束错误 !"},
{"未找到目标文件!"}
};
//---------------------------------------------------------------
CRapidFinder::CRapidFinder()
{
m_hThrds=NULL;
InitializeCriticalSection(&m_gCriticalSection);
ThreadSet();
}
CRapidFinder::CRapidFinder(HWND MainHwnd,CString MatchName,CString MatchDir)
{
m_hThrds=NULL;
InitializeCriticalSection(&m_gCriticalSection);
ThreadSet();
FinderSet(MainHwnd,MatchName,MatchDir);
}
CRapidFinder::~CRapidFinder()
{
DeleteCriticalSection(&m_gCriticalSection);
if(m_hExitEvent)CloseHandle(m_hExitEvent);
}
//———————————————————————————————————
void CRapidFinder::FinderSet(HWND MainHwnd,CString MatchName,CString MatchDir)
{
FinderReset();
m_MainhWnd=MainHwnd;
if(!MatchName.IsEmpty())
{
MatchName.MakeUpper();MatchDir.MakeUpper();
m_strFileName=MatchName;
m_Option|=OP_FILENAME;
}
m_strFileDir=MatchDir;
m_hExitEvent=CreateEvent(NULL,TRUE,FALSE,"RAPIDFINDER");
CreatePathList();
}
void CRapidFinder::ThreadSet(LONG MaxThreadCount,int priority)
{
m_Priority=priority;
m_ActiveCount=m_MaxThreadCount=MaxThreadCount;
if(m_hThrds)delete []m_hThrds;//释放线程句柄数组
m_hThrds=new HANDLE[MaxThreadCount];
}
void CRapidFinder::FindWithText(LPCTSTR lpText,int count)
{
if(!count)return ;
m_TextSize=count;
if(m_lpText)delete []m_lpText;
m_Option|=OP_FILETEXT;
m_lpText=new BYTE[count];
memcpy(m_lpText,lpText,count);
if(m_NextVal)delete []m_NextVal;
m_NextVal=new int[count];
CalNextPos();
}
void CRapidFinder::FinderReset()
{
m_lpText=NULL;
m_NextVal=NULL;
m_Option=0;
m_strFileName="";
m_strFileDir="";
m_DirList.RemoveAll();
ResetEvent(m_hExitEvent);
m_ExitCode=ERR;
}
void CRapidFinder::CreatePathList()
{
Trim(m_strFileDir);
if(m_strFileDir.IsEmpty())
{
SetErrNo(0);return ;
}
int np=0,op=0;
CString str;
while((np=m_strFileDir.Find(';',op))!=-1)
{
str=Trim(m_strFileDir.Mid(op,np-op));
str.TrimRight('\\');
if(!str.IsEmpty())m_DirList.AddTail((LPCTSTR)str);
op=np+1;
}
str=Trim(m_strFileDir.Mid(op,m_strFileDir.GetLength()-op));
str.TrimRight('\\');
if(!str.IsEmpty())m_DirList.AddTail((LPCTSTR)str);
}
//----------------------------------------------------------------------
BOOL CRapidFinder::StartFinder()
{
if(m_DirList.IsEmpty()){SetErrNo(0);return FALSE;}
PostMessage(m_MainhWnd,WM_THREADCOUNT,(WPARAM)m_ActiveCount,NULL);
DWORD ThreadID;
//创建主线程
HANDLE hMainThread=CreateThread(NULL,0,MainThreadProc,(LPVOID)this,CREATE_SUSPENDED,&ThreadID);
ASSERT(hMainThread);
BOOL re=SetThreadPriority(hMainThread,m_Priority);//调整优先级
ASSERT(re);
ResumeThread(hMainThread);
CloseHandle(hMainThread);
return TRUE;
}
void CRapidFinder::PauseFinder()
{
if(m_ExitCode==PAUSE)return ;
m_ExitCode=PAUSE;
SetEvent(m_hExitEvent);
Sleep(40);
}
void CRapidFinder::ResumeFinder()
{
SetEvent(m_hExitEvent);
}
void CRapidFinder::StopFinder()
{
if(m_ExitCode==STOP)return ;
if(m_ExitCode==PAUSE)
{
ResumeFinder();
Sleep(40);//延时
}
m_ExitCode=STOP;
SetEvent(m_hExitEvent);
}
//----------------------------------------------------------------------------------------------------
HANDLE CRapidFinder::StartThread(LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParam)
{
DWORD ThreadID;
CRapidFinder *finder=(CRapidFinder *)lpParam;
HANDLE htmp=CreateThread(NULL,0,lpStartAddress,lpParam,CREATE_SUSPENDED,&ThreadID);
BOOL re=SetThreadPriority(htmp,finder->m_Priority);
ASSERT(re);
ResumeThread(htmp);
return htmp;
}
//------------------------------------------------------------------------------------------------------
DWORD WINAPI CRapidFinder::MainThreadProc(LPVOID lpParam)
{
CRapidFinder *finder=(CRapidFinder *)lpParam;
resume:
//Reset
ResetEvent(finder->m_hExitEvent);
finder->m_ExitCode=ERR;
finder->m_ActiveCount=finder->m_MaxThreadCount;
PostMessage(finder->m_MainhWnd,WM_THREADCOUNT,(WPARAM)(finder->m_ActiveCount),NULL);
for(int i=0;i<finder->m_MaxThreadCount;i++)
finder->m_hThrds[i]=StartThread(ThreadProc,lpParam);
WaitForMultipleObjects(finder->m_MaxThreadCount,finder->m_hThrds,TRUE,INFINITE);
for(i=0;i<finder->m_MaxThreadCount;i++)
CloseHandle(finder->m_hThrds[i]); //关闭所有线程句柄
//查看线程退出原因
switch(finder->m_ExitCode)
{
case PAUSE:SendMessage(finder->m_MainhWnd,WM_THREADPAUSE,NULL,NULL);
ResetEvent(finder->m_hExitEvent);
//等待继续查找
WaitForSingleObject(finder->m_hExitEvent,INFINITE);
goto resume;
case EXIT:SendMessage(finder->m_MainhWnd,WM_THREADEXIT,EXIT,NULL);
finder->FinderReset();
break;;
case STOP:SendMessage(finder->m_MainhWnd,WM_THREADEXIT,STOP,NULL);
finder->FinderReset();
break;
default:finder->SetErrNo(1);return 0;
}
return 1;
}
//----------------------------------------------------------------------------------
DWORD WINAPI CRapidFinder::ThreadProc(LPVOID lpParam)
{
CRapidFinder *finder=(CRapidFinder *)lpParam;
CFileFind filefinder;
CStringList filelist;
CString PathStr;
CString CurPath;
int re;
BYTE bNewActive=1,bOldActive;
CString *lpFolder=new CString;
while(1)
{
bOldActive=bNewActive;
if(WaitForSingleObject(finder->m_hExitEvent,0)!=WAIT_TIMEOUT)
{
if(bOldActive)InterlockedDecrement(&finder->m_ActiveCount);
PostMessage(finder->m_MainhWnd,WM_THREADCOUNT,(WPARAM)finder->m_ActiveCount,NULL);
break;
}
if(!finder->m_ActiveCount)
{
SetEvent(finder->m_hExitEvent);
finder->m_ExitCode=finder->EXIT;
break;
}
//进入临界区
EnterCriticalSection(&finder->m_gCriticalSection);
if(finder->m_DirList.IsEmpty())bNewActive=0;
else
{
bNewActive=1;
*lpFolder=finder->m_DirList.RemoveHead();
CurPath=*lpFolder+_T("\\*.*");
}
LeaveCriticalSection(&finder->m_gCriticalSection);
//离开临界区
if(bNewActive!=bOldActive)
{
bNewActive?InterlockedIncrement(&finder->m_ActiveCount):InterlockedDecrement(&finder->m_ActiveCount);
PostMessage(finder->m_MainhWnd,WM_THREADCOUNT,(WPARAM)finder->m_ActiveCount,NULL);
}
else if(!bNewActive)continue;
SendMessage(finder->m_MainhWnd,WM_FINDERFOLDER,(WPARAM)lpFolder,NULL);
if(filefinder.FindFile(LPCTSTR(CurPath)))
{
do
{
re=filefinder.FindNextFile();
if(filefinder.IsDots())continue;
PathStr=filefinder.GetFilePath();
if(filefinder.IsDirectory())
{
EnterCriticalSection(&finder->m_gCriticalSection);
finder->m_DirList.AddTail(PathStr);
LeaveCriticalSection(&finder->m_gCriticalSection);
}
else filelist.AddTail(PathStr);
}while(re);
}
while(!filelist.IsEmpty())
{
PathStr=filelist.RemoveHead();
if(finder->MatchProc(PathStr))
SendMessage(finder->m_MainhWnd,WM_FINDERITEM,(WPARAM)&PathStr,NULL);
}
}
delete lpFolder;
filefinder.Close();
return 0;
}
//--------------------------------------------------------------------
BOOL __fastcall CRapidFinder::MatchProc(CString &findpath)
{
CString fname(findpath);
int pos=fname.ReverseFind('\\');
fname.MakeUpper();
if((m_Option&OP_FILENAME)&&(fname.Find(m_strFileName,pos+1)==-1))return false;
if((m_Option&OP_FILETEXT)&&!FindTextFromFile(findpath))return false;
return true;
}
BOOL __fastcall CRapidFinder::FindTextFromFile(CString &findpath)
{
CFile file;
if(NULL==file.Open(findpath.GetBuffer(0),CFile::modeRead|CFile::typeBinary))return false;
BYTE *Buffer=new BYTE[512];
int nRead;
if(!(nRead=file.Read(Buffer,512))){file.Close();return false;}
int i=0,j=0;
while(j<m_TextSize)
if(j==-1||Buffer[i]==m_lpText[j])
{
if(++i==nRead)
{
/*PeekAndPump();*/
if(!(nRead=file.Read(Buffer,512))){file.Close();return false;}
i=0;
}
j++;
}
else j=m_NextVal[j];
file.Close();
return true;
}
int* CRapidFinder::CalNextPos()
{
int j=0,k=-1;
m_NextVal[0]=-1;
while(j<m_TextSize-1)
if((k==-1)||(m_lpText[j]==m_lpText[k]))
{
j++;k++;
if(m_lpText[j]!=m_lpText[k])m_NextVal[j]=k;
else m_NextVal[j]=m_NextVal[k];
}
else k=m_NextVal[k];
return m_NextVal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -