采用stack实现的文件夹循环深度优先遍历的基类
来源:互联网 发布:我的世界linux启动器 编辑:程序博客网 时间:2024/06/07 03:27
一般情况下,我们在遍历文件夹时,都采用递归方式,但在wince平台下测试发现,当递归深度达到46级时,出现stack overflow而导致程序崩溃。为了解决这个问题,将递归改进为循环,这样理论上可以做到无限,只要内存一直满足的前提下。下面的代码完整展现了Windows平台(含WinCE)下,改进的文件遍历算法——循环深度优先遍历。
头文件:
#ifndef CFILEFINDER_H_#define CFILEFINDER_H_#include <Windows.h>#if 1#include "hswstack.h"#else#include "hswqueue.h"#endif#ifndef FILE_STRING_STD#define FILE_STRING_STD (260)#endif#ifndef CheckFilePath#define CheckFilePathLength(x) \ if(wcslen(x) >= FILE_STRING_STD)\ return #endif#ifndef _TAG_FILE_FOLDER#define _TAG_FILE_FOLDERtypedef struct tagFileFolder{ WCHAR wcName[FILE_STRING_STD]; void operator()(LPCTSTR lpfile) { if (this) { CheckFilePathLength(lpfile); wcscpy_s(wcName,FILE_STRING_STD,lpfile); } } void operator=(const struct tagFileFolder _right) { if (this) { CheckFilePathLength(_right.wcName); wcscpy_s(wcName,FILE_STRING_STD,_right.wcName); } } bool operator==(LPCTSTR lpfile)const { if (this != NULL) { return !(wcsicmp(this->wcName,lpfile)); } } bool operator==(const struct tagFileFolder _right)const { if (this != NULL) { return !(wcsicmp(this->wcName,_right.wcName)); } } tagFileFolder() { memset(wcName,0,FILE_STRING_STD); } tagFileFolder(LPCTSTR lpfile) { CheckFilePathLength(lpfile); wcscpy_s(wcName,FILE_STRING_STD,lpfile); }}tFileItem,*PFileItem;//此结构体可以根据不同的应用场景来扩展。可以增加文件的扩展名,创建日期,修改日期,大小等,可以增加文件的属性#endifclass CFileFinder//采用深度优先算法遍历文件夹及其子文件夹,不采用递归方式,采用循环方式{public: CFileFinder(); virtual ~CFileFinder();public: virtual BOOL Initialize() = 0;//初始化 virtual void UnInitialize() = 0;//反初始化 virtual BOOL UserFunction(LPCTSTR lpFolder, LPCTSTR lpFile) = 0;//遍历过程中,供派生类对象处理数据的接口 virtual BOOL ScanOver() = 0;//扫描结束后,供派生类对象处理扫描出来的文件的接口protected: virtual BOOL StartScan(LPCTSTR lpPath); virtual void StopScan();protected: CRITICAL_SECTION m_CS; __forceinline void Lock() {EnterCriticalSection(&m_CS);} __forceinline void Unlock() {LeaveCriticalSection(&m_CS);} virtual BOOL KillScanProc(); virtual BOOL CreateScanProc();private: volatile BOOL m_bAbort;//控制当前是否扫描文件 volatile BOOL m_bRunning;//控制扫描文件的线程退出与否 HANDLE m_hEvtScan; HANDLE m_hThread; static DWORD WINAPI FileFindProc(LPVOID lp);#if 1 HswStack<tFileItem> m_list_folder;//用于存放文件夹的链表#else HswQueue<tFileItem> m_list_folder;#endif virtual BOOL ScanFiles();};#ifdef UNDER_CE#include "ShlWapi.h"#pragma comment(lib,"shlwapi.lib")#else#include <io.h>#endif#endif
源文件:
#include "FileFinder.h"CFileFinder::CFileFinder(){ m_bRunning = FALSE; m_hThread = NULL; m_hEvtScan = NULL; m_bAbort = FALSE; InitializeCriticalSection(&m_CS);}CFileFinder::~CFileFinder(){ StopScan(); KillScanProc(); m_list_folder.free(); DeleteCriticalSection(&m_CS);}BOOL CFileFinder::StartScan(LPCTSTR lp){ BOOL b = FALSE;#ifdef UNDER_CE if (wcslen(lp) > 0 && PathFileExists(lp)) {#else WCHAR wPath[MAX_PATH]; wsprintf(wPath,L"%s\\",lp); if(wcslen(lp) > 0 && (0 == _waccess(wPath,0))) {#endif InterlockedExchange((LONG*)&m_bRunning, (LONG)TRUE); InterlockedExchange((LONG*)&m_bAbort,(LONG)FALSE); Lock(); m_list_folder.push(tFileItem(lp)); Unlock(); SetEvent(m_hEvtScan); b = TRUE; } return b;}void CFileFinder::StopScan(){ InterlockedExchange((LONG*)&m_bAbort,TRUE); RETAILMSG(1,(L"%s,%d,.size %d\n",TEXT(__FUNCTION__),__LINE__,m_list_folder.size()));}BOOL CFileFinder::CreateScanProc(){ if (NULL == m_hThread) { m_bRunning = TRUE; m_bAbort = FALSE; m_hEvtScan = ::CreateEvent(NULL,FALSE,FALSE,NULL); m_hThread = ::CreateThread(NULL,0,FileFindProc,this,0,NULL);#ifdef UNDER_CE int iThread = ::CeGetThreadPriority(::GetCurrentThread()); ::CeSetThreadPriority(m_hThread, iThread - 5);#endif } return 1;}BOOL CFileFinder::KillScanProc(){ if (m_hThread) {#ifdef UNDER_CE ::CeSetThreadPriority(m_hThread,CE_THREAD_PRIO_256_TIME_CRITICAL); #endif StopScan(); InterlockedExchange((LONG*)&m_bRunning, (LONG)FALSE); WaitForSingleObject(m_hThread,INFINITE); CloseHandle(m_hThread); CloseHandle(m_hEvtScan); m_hThread = NULL; m_hEvtScan = NULL; } return TRUE;}DWORD CFileFinder::FileFindProc(LPVOID lp){ CFileFinder *pThis = (CFileFinder*)lp; if (pThis != NULL) { DWORD dwWait; for (;pThis->m_bRunning;) { dwWait = ::WaitForSingleObject(pThis->m_hEvtScan, 800); switch(dwWait) { case WAIT_OBJECT_0: { pThis->Lock(); DWORD dwTick = GetTickCount(); BOOL ret = pThis->ScanFiles();//step1.扫描文件,并将文件存放在链表中 RETAILMSG(1,(L"scan time %d\n",GetTickCount()-dwTick)); if (ret) { //1、文件扫描完 pThis->ScanOver(); } pThis->Unlock(); } break; } } } return 56789;}BOOL CFileFinder::ScanFiles(){ TCHAR cs_temp_cur[FILE_STRING_STD]; tFileItem folder; WIN32_FIND_DATA filedata; BOOL bRet = TRUE; int itemp_folder_count = 0; int itemp_file_count = 0; while (!m_bAbort && m_list_folder.size() > 0 ) { m_list_folder.pop(folder);//pop函数的实现方式直接决定了遍历的方式是深度优先遍历还是广度优先遍历 //如果链表的push和pop操作都在链表的同一端,则类似栈操作,实现为深度优先遍历 //如果链表的push和pop分别在链表的头和尾操作,则类型队列,实现为广度优先遍历 wcscpy_s(cs_temp_cur, FILE_STRING_STD, folder.wcName); wcscat_s(cs_temp_cur, FILE_STRING_STD, L"\\*.*"); HANDLE hFind = FindFirstFile(cs_temp_cur, &filedata); if (hFind != INVALID_HANDLE_VALUE) { do { if (filedata.cFileName[0] == L'.') { continue; } if (FILE_ATTRIBUTE_HIDDEN == (filedata.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) { continue; } wsprintf(cs_temp_cur,L"%s\\%s",folder.wcName,filedata.cFileName); wcscpy_s(filedata.cFileName,MAX_PATH,cs_temp_cur); if (FILE_ATTRIBUTE_DIRECTORY == (filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )) { itemp_folder_count++; m_list_folder.push(tFileItem(cs_temp_cur)); } else { itemp_file_count++; UserFunction(folder.wcName,cs_temp_cur);} //Sleep(0); }while(!m_bAbort && FindNextFile(hFind, &filedata)); FindClose(hFind); } //Sleep(0); } int error = GetLastError(); if (m_bAbort || ((error != 18 && error != 0) || 4319 == error || 1609 == error || 3 == error || 1617 == error)) { bRet = FALSE; } m_list_folder.free(); printf("total file count %d,,,,,total folder count %d\n",itemp_file_count,itemp_folder_count); return bRet;}
hswstack.h文件可以在另一篇文章中找到。
0 0
- 采用stack实现的文件夹循环深度优先遍历的基类
- 采用邻接矩阵表示图的深度优先遍历搜索
- 图的深度优先遍历和广度优先遍历实现
- Python实现文件夹深度优先遍历
- 深度优先遍历的栈实现
- 深度优先算法遍历文件夹里面的各文件
- 图的深度优先和广度优先遍历及其实现
- 图的遍历之-DFS深度优先遍历C++实现
- 树的深度优先遍历
- 图的深度优先遍历
- 图的深度优先遍历
- 图的深度优先遍历
- 图的深度优先遍历
- 图的深度优先遍历
- 图的深度优先遍历
- 图的深度优先遍历
- 图的深度优先遍历
- 图的深度优先遍历
- [C++]函数后面加const修饰
- Java对象克隆(Clone)及Cloneable接口、Serializable接口的深入探讨
- 简单使用URLConnection、HttpURLConnection和HttpClient访问网络资源
- wireshark 实用过滤表达式(针对ip、协议、端口、长度和内容)
- java再复习-常用线程池
- 采用stack实现的文件夹循环深度优先遍历的基类
- Maven基础学习—Maven入门
- CodeForces #307 Div.2 B. ZgukistringZ
- Android酷炫实用的开源框架(UI框架)
- A页面跳转到B页面某一指定位置
- 射频识别技术漫谈(7)——ID卡
- 侧边栏的实现(三)
- 类方法、静态方法、属性
- node.js学习(五、基础js语法)