#ifndef _FIND_FILE_H_
#define _FIND_FILE_H_
#include <afxwin.h>
#include<queue>
struct CDirectoryNode:public CNoTrackObject
{
char m_szDir[MAX_PATH * 8];
};
class CRapidFinder
{
public:
friend UINT FindEntry(LPVOID lpParam);
CRapidFinder(int nMaxThread);
~CRapidFinder();
BOOL CheckFile(LPCTSTR lpszFileName);
CRITICAL_SECTION GetCriticalSection();
void AddDirectoryNode(CDirectoryNode* node);
void SetnThreadCount(int nCount);
long GetFindCount();
HANDLE m_hExitEvent;
private:
long m_nResultCount;
int m_nThreadCount;
std::queue<CDirectoryNode*> m_listDir;
CRITICAL_SECTION m_cs;
const int m_nMaxThread;
char m_szMatchName[MAX_PATH];
HANDLE m_hDirEvent;
};
#endif
#include <string.h>
#include "FindFile.h"
CRapidFinder::CRapidFinder(int nMaxThread):m_nMaxThread(nMaxThread)
{
m_nResultCount = 0;
m_nThreadCount = 0;
m_szMatchName[0] = '\0';
while(!m_listDir.empty())
{
m_listDir.pop();
}
m_hDirEvent = CreateEvent(NULL, FALSE, FALSE, _T("DirEvent"));
m_hExitEvent = CreateEvent(NULL, FALSE, FALSE, _T("ExitEvent"));
::InitializeCriticalSection(&m_cs);
}
CRapidFinder::~CRapidFinder()
{
CloseHandle(m_hDirEvent);
CloseHandle(m_hExitEvent);
DeleteCriticalSection(&m_cs);
}
CRITICAL_SECTION CRapidFinder::GetCriticalSection()
{
return m_cs;
}
BOOL CRapidFinder::CheckFile(LPCTSTR lpszFileName)
{
char szChar[MAX_PATH];
char szSearch[MAX_PATH * 8];
strcpy_s(szSearch, m_szMatchName);
strcpy_s(szChar, lpszFileName);
_strupr(szChar);
_strupr(szSearch);
if (strstr(szChar, szSearch))
{
return TRUE;
}
return FALSE;
}
void CRapidFinder::AddDirectoryNode(CDirectoryNode* node)
{
EnterCriticalSection(&m_cs);
m_listDir.push(node);
LeaveCriticalSection(&m_cs);
}
void CRapidFinder::SetnThreadCount(int nCount)
{
EnterCriticalSection(&m_cs);
m_nThreadCount = nCount;
LeaveCriticalSection(&m_cs);
}
long CRapidFinder::GetFindCount()
{
EnterCriticalSection(&m_cs);
int nCount = m_nResultCount;
LeaveCriticalSection(&m_cs);
return nCount;
}
UINT FindEntry(LPVOID lpParam)
{
CRapidFinder* pFinder = (CRapidFinder*)lpParam;
CDirectoryNode* pNode = nullptr;
BOOL bActive = TRUE;
while(1)
{
::EnterCriticalSection(&pFinder->GetCriticalSection());
if (pFinder->m_listDir.empty())
{
bActive = FALSE;
}
else
{
bActive = TRUE;
pNode = pFinder->m_listDir.front();
pFinder->m_listDir.pop();
}
::LeaveCriticalSection(&pFinder->m_cs);
if (!bActive)
{
::EnterCriticalSection(&pFinder->m_cs);
pFinder->m_nThreadCount--;
if (0 == pFinder->m_nThreadCount )
{
::LeaveCriticalSection(&pFinder->m_cs);
break;
}
LeaveCriticalSection(&pFinder->m_cs);
ResetEvent(pFinder->m_hDirEvent);
::WaitForSingleObject(pFinder->m_hDirEvent, INFINITE);
EnterCriticalSection(&pFinder->m_cs);
pFinder->m_nThreadCount++;
LeaveCriticalSection(&pFinder->m_cs);
bActive = TRUE;
continue;
}
WIN32_FIND_DATA fileData;
HANDLE hFinFile = INVALID_HANDLE_VALUE;
if (pNode->m_szDir[strlen(pNode->m_szDir) -1 ] != '\\')
{
strcat_s(pNode->m_szDir, MAX_PATH *8, "\\");
}
strcat_s(pNode->m_szDir, MAX_PATH*8, "*.*");
hFinFile = FindFirstFile(pNode->m_szDir, &fileData);
if (hFinFile != INVALID_HANDLE_VALUE)
{
do
{
if (fileData.cFileName[0] == '.')
{
continue;
}
if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
CDirectoryNode* p = new CDirectoryNode;
strncpy_s(p->m_szDir, pNode->m_szDir, strlen(pNode->m_szDir) -3);
strcat_s(p->m_szDir, fileData.cFileName);
EnterCriticalSection(&pFinder->m_cs);
pFinder->m_listDir.push(p);
LeaveCriticalSection(&pFinder->m_cs);
SetEvent(pFinder->m_hDirEvent);
}
else
{
if (pFinder->CheckFile(fileData.cFileName))
{
::EnterCriticalSection(&pFinder->m_cs);
InterlockedIncrement((long*)&pFinder->m_nResultCount);
::LeaveCriticalSection(&pFinder->m_cs);
printf("%s \n", fileData.cFileName);
}
}
} while (::FindNextFile(hFinFile, &fileData));
}
delete pNode;
pNode = nullptr;
}
SetEvent(pFinder->m_hDirEvent);
if (WaitForSingleObject(pFinder->m_hDirEvent, 0) != WAIT_TIMEOUT)
{
SetEvent(pFinder->m_hExitEvent);
}
return 0;
}
void main()
{
CRapidFinder* pFinder = new CRapidFinder(64);
CDirectoryNode* pNode = new CDirectoryNode;
char szPath[] = _T("C:\\");
char szFile[] = _T("stdafx");
strcpy_s(pNode->m_szDir, MAX_PATH*8, szPath);
pFinder->AddDirectoryNode(pNode);
for (int i = 0; i < 64; ++i)
{
AfxBeginThread(FindEntry, (LPVOID)pFinder);
}
WaitForSingleObject(pFinder->m_hExitEvent, INFINITE);
printf("最终查找文件的个数:%d \n", pFinder->GetFindCount());
}