首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

C++ 目錄遍歷實戰:MFC CFileFind 遞迴掃描、專案設定與 Unicode/多位元組相容

     編輯:更多程式設計知識

VC++ 專案需遍歷目錄樹時,MFC `CFileFind` 提供便利封裝。本文涵蓋專案屬性設定、標頭檔引用、遞迴掃描完整程式碼、關鍵 API (`FindFile`/`FindNextFile`/`IsDirectory`/`IsDots`)、多位元組/Unicode 相容宏 (`_T`, `LPCTSTR`)、`TRACE` 除錯輸出與常見錯誤。

專案設定 (必要步驟)

  1. 專案屬性 → 一般 → 使用 MFC:選「在共用 DLL 中使用 MFC」或「在靜態程式庫中使用 MFC」。
  2. 標頭檔引用:`#include ` (或 `stdafx.h` 已包含)。
  3. 字元集設定:屬性 → 進階 → 字元集:建議「使用多位元組字元集」 (MBCS) 以簡化 `_T`/`LPCTSTR` 轉換,或統一 Unicode 並嚴格使用 `CString`/`TCHAR`。

遞迴遍歷標準程式碼 (Microsoft 範例改良)


#include 
#include 

void Recurse(LPCTSTR path) {
    CFileFind finder;
    CString wildcard(path);
    wildcard += _T("\\*.*");  // _T 宏適配 MBCS/Unicode

    BOOL working = finder.FindFile(wildcard);
    while (working) {
        working = finder.FindNextFile();  // 必須先呼叫 FindNextFile 再存取其他屬性

        if (finder.IsDots()) continue;    // 跳過 "." 與 ".."

        if (finder.IsDirectory()) {
            CString fullPath = finder.GetFilePath();
            TRACE(_T("%s\n"), (LPCTSTR)fullPath);  // Debug 輸出
            std::wcout << fullPath.GetString() << std::endl;  // 主控台輸出 (Unicode)
            Recurse(fullPath);  // 遞迴
        }
        // 檔案處理可在這裡加入
        // else { ... finder.GetFileName() ... }
    }
    finder.Close();
}

int main() {
    Recurse(_T("C:\\"));  // 從 C 槽根目錄開始 (需權限)
    return 0;
}

關鍵 API 與流程解析

方法用途注意事項
`FindFile(wildcard)`啟動搜尋,回傳 BOOL支援萬用字元 `*`, `?`
`FindNextFile()`移至下一項,**必須在存取屬性前呼叫至少一次**未呼叫直接 `GetFileName()` 會斷言失敗
`IsDots()`檢查是否為 "." 或 ".."避免無限遞迴
`IsDirectory()`判斷目錄含重新解析點/連結
`GetFilePath()`取得完整路徑回傳 `CString`
`GetFileName()`取得檔名不含路徑
`GetLength()`檔案大小 (位元組)`ULONGLONG` (64-bit)
`GetCreationTime()`/`GetLastWriteTime()`時間戳輸出 `CTime` 物件
`Close()`釋放搜尋控制代碼RAII 風格建議自行封裝

`TRACE` 宏說明

  • Debug 建置輸出至 **Visual Studio 輸出視窗**。
  • Release 建置**自動編譯為空操作** (零開銷)。
  • 格式類 `printf`:`TRACE(_T("File: %s, Size: %llu\n"), name, size);`。

Unicode / MBCS 相容撰寫技巧

  • 字串常值加 `_T("...")` 或 `TEXT("...")`。
  • API 使用 `LPCTSTR` / `LPTSTR` / `CString`。
  • 主控台輸出 Unicode 用 `std::wcout` + `CString::GetString()`。
  • 檔案 I/O 需注意編碼:`CStdioFile` 文字模式自動處理,二進位用 `CFile::modeBinary`。

現代 C++ 替代方案 (C++17 ``)


#include 
#include 
namespace fs = std::filesystem;

void scan(const fs::path& root) {
    for (auto& entry : fs::recursive_directory_iterator(root)) {
        if (entry.is_directory()) {
            std::cout << "[DIR]  " << entry.path() << '\n';
        } else {
            std::cout << "[FILE] " << entry.path() << " (" << entry.file_size() << " bytes)\n";
        }
    }
}

優勢:標準庫、跨平台、無 MFC 相依、支援迭代器範圍 for、錯誤處理用 `std::error_code` 避免例外。

常見錯誤與排查

既有 MFC 專案用 `CFileFind` 最便利;新專案或跨平台需求**強烈建議 C++17 ``**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
現象原因解決
編譯錯誤 `CFileFind` 未定義未設定「使用 MFC」或未包含 `afx.h`專案屬性設定 MFC、包含 `afx.h`
遞迴無限循環未 `continue` 跳過 `IsDots()`務必 `if (finder.IsDots()) continue;`
`GetFilePath()` 回傳空未先呼叫 `FindNextFile()`循環開頭 `working = finder.FindNextFile();`
權限拒絕 (Access Denied)掃描系統目錄 (System Volume Information 等)捕捉 `CFileException` 或檢查 `GetLastError()`,略過不可讀目錄
路徑超過 MAX_PATH (260)深層目錄使用 `\\?\` 前綴或改用 `` (支援長路徑)