16,471
社区成员
发帖
与我相关
我的任务
分享
#pragma once
#include <Windows.h>
#include <process.h>
#include <atlstr.h>
#include <vector>
#include <stack>
using namespace std;
#define MAXTHREADS 64
class CFileScan
{
public:
CFileScan(void);
~CFileScan(void);
ULONG GetFileCount(void);
BOOL BeginScan(LPCWSTR lpTargetDir,LPCWSTR lpExt,ULONG uThreadCounts);
private:
static UINT __stdcall ThreadFun(void* Param);
void SearchFile(void);
private:
stack<CString,vector<CString>> m_stkPath; //用于存储路径
LONG m_lResultCnt; //保存文件数
CString m_strExt; //保存拓展名字符串
HANDLE m_hDirEvent; //文件夹事件对象
HANDLE m_hExitEvent; //退出事件对象
ULONG m_uThread; //线程活动数量
CRITICAL_SECTION m_cs; //临界区对象,保持线程同步
};
#include "FileScan.h"
#include "DebugHelp.h"
CFileScan::CFileScan(void)
{
m_lResultCnt = 0;
m_uThread = 0;
InitializeCriticalSection(&m_cs);
m_hDirEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
m_hExitEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
}
CFileScan::~CFileScan(void)
{
CloseHandle(m_hDirEvent);
m_hDirEvent = INVALID_HANDLE_VALUE;
CloseHandle(m_hExitEvent);
m_hExitEvent = INVALID_HANDLE_VALUE;
DeleteCriticalSection(&m_cs);
}
BOOL CFileScan::BeginScan(LPCWSTR lpTargetDir,LPCWSTR lpExt,ULONG uThreadCounts)
{
if (!GOOD_HANDLE(m_hDirEvent))
{
DisplayInfoW(__FUNCTIONW__,L"DirEvent is invalid,return false");
return FALSE;
}
if (!GOOD_HANDLE(m_hExitEvent))
{
DisplayInfoW(__FUNCTIONW__,L"ExitEvent is invalid,return false");
return FALSE;
}
if (uThreadCounts > MAXTHREADS)
{
DisplayInfoExW(__FUNCTIONW__,L"ThreadCounts = %d is bigger than %d",uThreadCounts,MAXTHREADS);
return FALSE;
}
m_strExt = lpExt;
m_stkPath.push(lpTargetDir);
m_uThread = uThreadCounts;
HANDLE h[MAXTHREADS];
for(ULONG i = 0; i < m_uThread; i++)
{
h[i] = (HANDLE)_beginthreadex(NULL,0,&CFileScan::ThreadFun,static_cast<LPVOID>(this),0,NULL);
}
WaitForSingleObject(m_hExitEvent,INFINITE);
for(ULONG j = 0; j < m_uThread; j++)
{
CloseHandle(h[j]);
h[j] = INVALID_HANDLE_VALUE;
}
return TRUE;
}
ULONG CFileScan::GetFileCount(void)
{
return m_lResultCnt;
}
UINT __stdcall CFileScan::ThreadFun(void* Param)
{
static_cast<CFileScan*>(Param)->SearchFile();
return 0;
}
void CFileScan::SearchFile(void)
{
WIN32_FIND_DATA FindFileData;
HANDLE hListFile = INVALID_HANDLE_VALUE;
BOOL bActive = TRUE; //提示当前线程的状态
CString strFilePath;
CString strFullPath;
while(TRUE)
{
/*判断路径栈是否为空,为空设置线程状态,不为空则取得顶部路径*/
EnterCriticalSection(&m_cs);
if(m_stkPath.empty())
{
bActive = FALSE;
}
else
{
strFilePath = m_stkPath.top();
m_stkPath.pop();
}
LeaveCriticalSection(&m_cs);
/*判断线程应有状态,如果状态为假,进入等待*/
if(!bActive)
{
EnterCriticalSection(&m_cs);
m_uThread--;
if(m_uThread==0)
{
LeaveCriticalSection(&m_cs);
break;
}
LeaveCriticalSection(&m_cs);
ResetEvent(m_hDirEvent);
WaitForSingleObject(m_hDirEvent,INFINITE);
/*线程再次活动后,进入下一轮循环*/
EnterCriticalSection(&m_cs);
m_uThread++;
LeaveCriticalSection(&m_cs);
bActive = TRUE;
continue;
}
if (strFilePath.Right(1) != L"\\")
{
strFilePath += L"\\";
}
strFilePath += L"*.*";
hListFile = FindFirstFile(strFilePath,&FindFileData);
if (GOOD_HANDLE(hListFile))
{
do
{
strFullPath = strFilePath.TrimRight(L"*.*") + FindFileData.cFileName;
if(lstrcmp(FindFileData.cFileName,L".") == 0||lstrcmp(FindFileData.cFileName,L"..") == 0)
{
continue;
}
if(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
{
EnterCriticalSection(&m_cs);
m_stkPath.push(strFullPath);
LeaveCriticalSection(&m_cs);
SetEvent(m_hDirEvent);
}
else
{
EnterCriticalSection(&m_cs);
int curPos = 0;
CString strExt = strFullPath.Right(3);
while(TRUE)
{
CString resToken = m_strExt.Tokenize(L"|", curPos);
if(resToken.IsEmpty())
{
break;
}
if (0 == strExt.CompareNoCase(resToken))
{
InterlockedIncrement((LPLONG)&m_lResultCnt);
DisplayInfoW(__FUNCTIONW__,strFullPath.GetBuffer());
}
}
LeaveCriticalSection(&m_cs);
}
}
while(FindNextFile(hListFile, &FindFileData));
FindClose(hListFile);
hListFile = INVALID_HANDLE_VALUE;
}
else
{
//部分文件夹本来就无法打开,比如E:\System Volume Information\*.*
//此时如果输出错误的话,影响审美
//DWORD dwError = GetLastError();
//SetLastError(dwError);
//DisplayErrorW(__FUNCTIONW__,dwError,L"FindFirstFile");
}
}
SetEvent(m_hDirEvent);
if(WaitForSingleObject(m_hDirEvent,0) != WAIT_TIMEOUT)
{
SetEvent(m_hExitEvent);
}
}
CFileScan scan;
scan.BeginScan(L"E:",L"txt|doc",5);
ULONG uFileCount = scan.GetFileCount();
DisplayInfoExW(__FUNCTIONW__,L"file counts = %d",uFileCount);