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

C/C++跨平台讀取目錄下所有文件名稱的方法總結

     編輯:程式設計疑難解答

核心結論

C/C++ 標準庫 (C17/C++17 前) **無統一目錄遍歷 API**,必須調用**平台特定系統調用**或使用**第三方庫**。

方案一:C++17 std::filesystem (現代標準、首選)

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main() {
    fs::path dir = "C:/MyProject/data"; // 或 "/home/user/data"
    try {
        for (const auto& entry : fs::directory_iterator(dir)) {
            std::cout << entry.path().filename().string() << '\n'; // 僅文件名
            // entry.path().string() // 完整路徑
            // entry.is_directory() / is_regular_file() / is_symlink()
        }
    } catch (fs::filesystem_error& e) {
        std::cerr << "Error: " << e.what() << '\n';
    }
    return 0;
}

✅ 跨平台 (Windows/Linux/macOS)、面向對象、支持遞歸 (`recursive_directory_iterator`)、編譯需 `-lstdc++fs` (GCC<9) 或 `/std:c++17` (MSVC)。

方案二:POSIX API (Linux/macOS/Unix 原生)

#include <dirent.h>
#include <stdio.h>
#include <string.h>

void list_files(const char* path) {
    DIR* dir = opendir(path);
    if (!dir) { perror("opendir"); return; }

    struct dirent* entry;
    while ((entry = readdir(dir)) != NULL) {
        // 過濾 . 和 ..
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
        printf("%s\n", entry->d_name);
        // entry->d_type: DT_REG(文件), DT_DIR(目錄), DT_LNK(鏈接)
    }
    closedir(dir);
}

方案三:Windows API (原生、高性能)

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

void list_files_windows(LPCTSTR path) {
    WIN32_FIND_DATA findData;
    HANDLE hFind = FindFirstFile((std::string(path) + "\\*").c_str(), &findData);
    if (hFind == INVALID_HANDLE_VALUE) return;

    do {
        if (_tcscmp(findData.cFileName, _T(".")) == 0 || 
            _tcscmp(findData.cFileName, _T("..")) == 0) continue;
        
        _tprintf(_T("%s\n"), findData.cFileName);
        // findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY 判斷目錄
    } while (FindNextFile(hFind, &findData));
    FindClose(hFind);
}

✅ 獲取更多元數據(創建時間、大小、屬性),支持大文件、長路徑 (`\\?\` 前綴)。

方案四:跨平台第三方庫 (避免手寫 #ifdef)

庫語言特點
Boost.FilesystemC++C++17 filesystem 前身、極其成熟、Header-only 可選
dirent.h (Windows 移植版)C在 Windows 模擬 POSIX `dirent.h`,單頭文件,輕量
libuvCNode.js 底層庫、異步非阻塞、跨平台文件系統操作
Qt QDir / QFileInfoC++Qt 框架項目首選、豐富 API、信號槽異步

遞歸遍歷模板 (C++17)

void traverse_recursive(const fs::path& root, int depth = 0) {
    try {
        for (const auto& entry : fs::recursive_directory_iterator(root)) {
            // 縮進顯示層級
            std::cout << std::string(entry.depth() * 2, ' ') 
                      << (entry.is_directory() ? "[D] " : "[F] ")
                      << entry.path().filename() << '\n';
        }
    } catch (fs::filesystem_error& e) {
        std::cerr << "Traverse error: " << e.what() << '\n';
    }
}

常見需求擴展

需求實現要點
過濾擴展名`entry.path().extension() == ".txt"` / `strstr(entry->d_name, ".log")`
按大小/時間排序收集到 `vector` 再 `std::sort` (需 `file_size`, `last_write_time`)
獲取完整路徑`entry.path().string()` / `path + "/" + entry->d_name`
處理中文/Unicode 路徑Windows 用 `FindFirstFileW` + `wchar_t`;C++17 `fs::path` 原生支持 UTF-8

總結

C++17 及以上項目請直接用 ``,一行代碼跨平台。舊標準或純 C 項目:Linux 用 `dirent.h`,Windows 用 `FindFirstFile`,或引入 `dirent.h` 移植版統一代碼。避免手寫 `#ifdef _WIN32` 分支,維護成本高且易出錯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved