在C++17中,标准库加入了<filesystem>头文件,提供了跨平台的文件系统操作接口。本文将演示如何使用std::filesystem实现一个递归遍历目录、收集文件信息,并按文件大小从大到小排序的程序。
1. 关键概念
| 名称 | 说明 |
|---|---|
std::filesystem::path |
表示文件路径的类型 |
std::filesystem::directory_iterator |
迭代器,遍历指定目录下的文件与子目录(不递归) |
std::filesystem::recursive_directory_iterator |
递归迭代器,遍历目录树中所有文件与目录 |
std::filesystem::file_size |
获取文件大小(字节) |
std::filesystem::is_regular_file |
判断是否为常规文件 |
2. 代码实现
#include <iostream>
#include <filesystem>
#include <vector>
#include <algorithm>
namespace fs = std::filesystem;
// 文件信息结构体
struct FileInfo {
fs::path path;
std::uintmax_t size; // 文件大小
};
// 递归遍历目录,收集所有常规文件
std::vector <FileInfo> collect_files(const fs::path& root) {
std::vector <FileInfo> files;
if (!fs::exists(root) || !fs::is_directory(root)) {
std::cerr << "路径不存在或不是目录: " << root << '\n';
return files;
}
for (const auto& entry : fs::recursive_directory_iterator(root)) {
try {
if (fs::is_regular_file(entry.path())) {
FileInfo fi{entry.path(), fs::file_size(entry.path())};
files.push_back(std::move(fi));
}
} catch (const fs::filesystem_error& e) {
std::cerr << "读取文件失败: " << e.what() << '\n';
// 继续遍历其他文件
}
}
return files;
}
// 按文件大小排序
void sort_by_size(std::vector <FileInfo>& files) {
std::sort(files.begin(), files.end(),
[](const FileInfo& a, const FileInfo& b) {
return a.size > b.size; // 大到小
});
}
// 打印结果
void print_files(const std::vector <FileInfo>& files) {
for (const auto& fi : files) {
std::cout << std::left << std::setw(8) << fi.size << " " << fi.path.string() << '\n';
}
}
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cerr << "用法: " << argv[0] << " <目录路径>\n";
return 1;
}
fs::path root(argv[1]);
auto files = collect_files(root);
if (files.empty()) {
std::cout << "未找到任何文件。\n";
return 0;
}
sort_by_size(files);
std::cout << "按文件大小从大到小排序的文件列表(共 " << files.size() << " 个文件):\n";
print_files(files);
return 0;
}
3. 代码说明
-
collect_files- 使用
fs::recursive_directory_iterator遍历所有子目录。 - 通过
fs::is_regular_file判断是否为普通文件。 - 捕获
fs::filesystem_error,避免因权限或损坏文件导致程序中断。
- 使用
-
sort_by_sizestd::sort与自定义比较器实现从大到小排序。
-
print_files- 采用宽度对齐输出文件大小,方便查看。
-
main- 接收命令行参数指定根目录。
- 调用上述函数完成工作。
4. 编译与运行
# 需要支持 C++17 的编译器
g++ -std=c++17 -O2 -Wall -Wextra -o dirscan dirscan.cpp
# 运行
./dirscan /path/to/your/directory
5. 常见问题与调优
| 问题 | 解决方案 |
|---|---|
| 读取大文件夹时占用内存过多 | 使用分块处理或只输出前 N 条记录 |
| 遇到符号链接导致循环 | recursive_directory_iterator 可传入 fs::directory_options::skip_permission_denied 或手动过滤 |
| 需要统计文件类型 | 在 FileInfo 中添加 fs::file_type 字段,并在遍历时记录 entry.status().type() |
6. 小结
`
` 提供了极简且跨平台的文件系统接口。通过 `recursive_directory_iterator`、`file_size`、`is_regular_file` 等工具,可以轻松实现目录遍历、文件筛选、信息收集等常见需求。本文演示的代码结构清晰,易于扩展,例如添加文件内容哈希、时间戳排序等功能。希望对你在 C++ 项目中的文件系统操作有所帮助。