C++函數(shù):文件遍歷小函數(shù)的設(shè)計(jì)實(shí)例

字號:

之前寫過 關(guān)于 win32 下磁盤的遍歷方法,下面是將里面實(shí)現(xiàn)的磁盤遍歷函數(shù)重新設(shè)計(jì)了一下,因?yàn)榇疟P遍歷,文件夾遍歷在很多時(shí)候還是很常見的,為了不修改遍歷的函數(shù)體,我將處理文件的部分交由一個(gè)回調(diào)函數(shù)去處理,這樣的話,你甚至可以把下面的代碼寫在dll里面,需要進(jìn)行文件遍歷的地方,只要實(shí)現(xiàn)一個(gè)回調(diào)函數(shù)傳進(jìn)去就可以了。
    函數(shù)聲明:
    // 函數(shù) : ScanDirectory
    // 功能 : 遍歷一個(gè)目錄,傳入一個(gè)函數(shù)指針
    // 返回值 : BOOL
    // 參數(shù) : const TCHAR *pszPath 傳入路徑
    // 參數(shù) : LPSCANDISK_START_ROUTINE lpFunAddress 函數(shù)指針回調(diào)指針
    // 參數(shù) : PVOID lpParam 回調(diào)函數(shù)參數(shù)
    // 參數(shù) : BOOL bIsRecur/* = TRUE*/ 是否遞歸
    // 附注 : 回調(diào)函數(shù)原型 DWORD WINAPI ScanProc(TCHAR *pFilePath, LPVOID lpParameter);
    // 回調(diào)函數(shù)的第一個(gè)參數(shù)是掃描到一個(gè)文件的全名typedef DWORD (WINAPI *LPSCANDISK_START_ROUTINE)(TCHAR *pFilePath, LPVOID lpParameter);
    BOOL ScanDirectory
    (const TCHAR *pszPath, LPSCANDISK_START_ROUTINE lpFunAddress, PVOID lpParam, BOOL bIsRecur = TRUE) 函數(shù)實(shí)現(xiàn): // 函數(shù) : ScanDirectory
    // 功能 : 遍歷一個(gè)目錄,傳入一個(gè)函數(shù)指針
    // 返回值 : BOOL
    // 參數(shù) : const TCHAR *pszPath 傳入路徑
    // 參數(shù) : LPSCANDISK_START_ROUTINE lpFunAddress 函數(shù)指針回調(diào)指針
    // 參數(shù) : PVOID lpParam 回調(diào)函數(shù)參數(shù)
    // 參數(shù) : BOOL bIsRecur/* = TRUE*/ 是否遞歸
    // 附注 : 回調(diào)函數(shù)原型 DWORD WINAPI ScanProc(TCHAR *pFilePath, LPVOID lpParameter);
    // 回調(diào)函數(shù)的第一個(gè)參數(shù)是掃描到一個(gè)文件的全名
    BOOL ScanDirectory(const TCHAR *pszPath, LPSCANDISK_START_ROUTINE lpFunAddress, PVOID lpParam, BOOL bIsRecur/* = TRUE*/)
    {
    BOOL bRet = FALSE;
    TCHAR *s = NULL;
    HANDLE hFind = NULL;
    WIN32_FIND_DATA fd = {0};
    TCHAR szFileName[MAX_PATH] = TEXT("");
    ::lstrcpy(szFileName, pszPath);
    s = szFileName + ::lstrlen(szFileName);
    if (*(s-1) != TEXT(’\\’))
    *s++ = TEXT(’\\’);
    ::lstrcpy(s, TEXT("*.*"));
    hFind = FindFirstFile(szFileName, &fd);
    if (hFind == INVALID_HANDLE_VALUE)
    goto Exit0;
    do
    {
    // 過濾
    if (::lstrcmpi(TEXT("."), fd.cFileName) == 0 || ::lstrcmpi(TEXT(".."), fd.cFileName) == 0)
    continue;
    ::lstrcpy(s, fd.cFileName);
    *(s + ::lstrlen(fd.cFileName)) = L’\0’;
    // 如果是文件夾則遞歸
    if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && bIsRecur)
    {
    ScanDirectory(szFileName, lpFunAddress, lpParam, bIsRecur);
    }
    else
    {
    // 對文件進(jìn)行處理
    if (lpFunAddress)
    lpFunAddress(szFileName, lpParam);
    }
    }while(::FindNextFile(hFind, &fd));
    bRet = TRUE;  
    Exit0:
    if( hFind != INVALID_HANDLE_VALUE )
    {
    ::FindClose( hFind );
    hFind = NULL;
    }
    return bRet;
    }
    不過這樣的實(shí)現(xiàn)有個(gè)小缺陷,文件特別多的話,效率會比較低,因?yàn)槊恳粋€(gè)文件都調(diào)用了一次回調(diào)函數(shù),其實(shí)接口還可以設(shè)計(jì)一個(gè)過濾器出來,讓掃描函數(shù)只對我們感興趣的文件進(jìn)行回調(diào),考試,大提示再就是文件夾的處理,也可以進(jìn)行回調(diào),具體怎么做大家也可以練練手