www.pudn.com > SouMP3.rar > 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;im_MaxThreadCount;i++) 
	   finder->m_hThrds[i]=StartThread(ThreadProc,lpParam); 
 
   WaitForMultipleObjects(finder->m_MaxThreadCount,finder->m_hThrds,TRUE,INFINITE); 
 
   for(i=0;im_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