在C++17标准中,STL新增了<filesystem>头文件,提供了一套统一的跨平台文件系统API。相比传统的<dirent.h>(POSIX)或<windows.h>(Windows)等专用库,std::filesystem可以让我们用同一套代码完成文件/目录的创建、删除、遍历、属性查询等操作,无需关心底层平台差异。
下面我们用一个完整的示例程序来演示:
#include <iostream>
#include <filesystem>
#include <vector>
#include <chrono>
#include <iomanip>
namespace fs = std::filesystem;
// 用来格式化时间戳
std::string format_time(const fs::file_time_type& ftime)
{
using namespace std::chrono;
auto sctp = system_clock::to_time_t(ftime);
std::tm tm{};
#if defined(_MSC_VER)
localtime_s(&tm, &sctp);
#else
localtime_r(&sctp, &tm);
#endif
std::ostringstream oss;
oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
// 递归遍历目录,返回所有文件路径
std::vector<fs::path> list_files(const fs::path& dir)
{
std::vector<fs::path> files;
if (!fs::exists(dir) || !fs::is_directory(dir))
return files;
for (auto const& entry : fs::recursive_directory_iterator(dir))
{
if (fs::is_regular_file(entry))
files.push_back(entry.path());
}
return files;
}
int main()
{
try
{
// 1. 创建目录
fs::path dir = "demo_dir";
if (!fs::exists(dir))
{
fs::create_directories(dir);
std::cout << "目录创建: " << dir << '\n';
}
// 2. 创建文件
fs::path file = dir / "hello.txt";
std::ofstream ofs(file);
ofs << "Hello, std::filesystem!\n";
ofs.close();
std::cout << "文件创建: " << file << '\n';
// 3. 查询属性
auto perms = fs::status(file).permissions();
std::cout << "文件权限: ";
std::cout << ((perms & fs::perms::owner_read) != fs::perms::none ? "r" : "-");
std::cout << ((perms & fs::perms::owner_write) != fs::perms::none ? "w" : "-");
std::cout << ((perms & fs::perms::owner_exec) != fs::perms::none ? "x" : "-") << '\n';
// 4. 获取文件大小
std::cout << "文件大小: " << fs::file_size(file) << " bytes\n";
// 5. 获取修改时间
std::cout << "上次修改时间: " << format_time(fs::last_write_time(file)) << '\n';
// 6. 递归遍历
std::cout << "目录下所有文件:\n";
auto files = list_files(dir);
for (auto const& f : files)
{
std::cout << " " << f << '\n';
}
// 7. 删除文件
fs::remove(file);
std::cout << "文件已删除: " << file << '\n';
// 8. 删除目录(空目录)
fs::remove(dir);
std::cout << "目录已删除: " << dir << '\n';
}
catch (const fs::filesystem_error& e)
{
std::cerr << "文件系统错误: " << e.what() << '\n';
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
代码说明
-
命名空间别名
namespace fs = std::filesystem;方便使用。 -
时间格式化
std::filesystem::file_time_type在不同平台内部是不同类型,需要先转换为std::time_t再格式化。示例兼容 MSVC 与 GCC/Clang。 -
递归遍历
fs::recursive_directory_iterator简单实现深度优先遍历。若只需要浅层遍历,可改为fs::directory_iterator。 -
错误处理
所有文件系统操作可能抛出std::filesystem_error,建议使用 try‑catch 捕获。 -
权限检查
fs::perms枚举支持位运算,可以快速判断可读/写/执行权限。 -
创建与删除
fs::create_directories能一次性创建多级目录。删除时remove仅能删除空目录或单个文件,若要递归删除文件夹请使用fs::remove_all。
常见陷阱
- Windows 兼容:Windows 下面文件路径使用反斜杠
\,但std::filesystem允许使用正斜杠/,并自动转换。若需要原始 Windows 路径,可使用std::filesystem::path::generic_string()或wstring。 - 编码:在 Windows 上,文件路径若包含非 ASCII 字符,最好使用
std::filesystem::path::wstring()或在wmain程序中使用宽字符。 - 符号链接:
fs::symlink_status与fs::status区别;后者会跟随链接,前者不跟随。
结论
std::filesystem 是 C++17 之后统一的文件系统 API,几乎涵盖了所有常见需求,消除了手写平台差异代码的繁琐。掌握它可以让你的 C++ 项目在 Linux、macOS、Windows 上都能保持同一套代码,极大提升可维护性与开发效率。