C/C++ 標準庫 (C17/C++17 前) **無統一目錄遍歷 API**,必須調用**平台特定系統調用**或使用**第三方庫**。
#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)。
#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);
}
#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);
}
✅ 獲取更多元數據(創建時間、大小、屬性),支持大文件、長路徑 (`\\?\` 前綴)。
| 庫 | 語言 | 特點 |
|---|---|---|
| Boost.Filesystem | C++ | C++17 filesystem 前身、極其成熟、Header-only 可選 |
| dirent.h (Windows 移植版) | C | 在 Windows 模擬 POSIX `dirent.h`,單頭文件,輕量 |
| libuv | C | Node.js 底層庫、異步非阻塞、跨平台文件系統操作 |
| Qt QDir / QFileInfo | C++ | Qt 框架項目首選、豐富 API、信號槽異步 |
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 及以上項目請直接用 `