std::filesystem::last_write_time仅获取最后写入时间,返回file_time_type需转为system_clock::time_point才能格式化输出。

怎么用 std::filesystem::last_write_time 获取文件最后修改时间
它不能获取“最后访问时间”,只能拿到“最后写入时间”——这是最常被误解的一点。C++20 的 std::filesystem 标准库压根没提供跨平台的 last_access_time 接口,last_write_time 是唯一稳定可用的时间戳函数。
实操上直接调用就行,但要注意返回值类型是 file_time_type,不是 time_t 或 system_clock::time_point,不能直接丢给 std::ctime 打印:
namespace fs = std::filesystem;
auto tp = fs::last_write_time("config.json");
// tp 是 fs::file_time_type,需转换才能格式化
auto sctp = fs::file_time_type::clock::to_sys(tp);
std::cout << std::asctime(std::localtime(&std::chrono::system_clock::to_time_t(sctp)));
-
fs::last_write_time抛异常(filesystem_error)当路径不存在、无权限或不是常规文件时,务必 try/catch - Windows 下该函数实际读取的是 NTFS 的
LastWriteTime;Linux 下对应st_mtime,行为一致 - 若传入目录,返回的是目录元数据(inode)的修改时间,不是其内容变更时间
为什么没有 last_access_time?不同系统差异太大
根本原因不是标准偷懒,而是各系统对“访问时间”的语义和更新策略分歧严重:
- Linux 默认挂载 ext4 时启用
relatime,只在 mtime/ctime 更新或上次 atime 超过 24 小时才写 atime,stat返回的值可能几天没变 - macOS 自 10.13 起默认禁用 atime 更新(
noatime),除非显式挂载参数开启 - Windows 的
LastAccessTime在 Server 2003 后也默认关闭更新,注册表项EnableLastAccess需手动设为 1
所以 C++ 标准委员会干脆不封装这个不可靠、不可控、非必需的字段——你真需要,得用平台 API:GetFileInformationByHandle(Win32)或 stat + st_atime(POSIX),但结果很可能和用户直觉不符。
立即学习“C++免费学习笔记(深入)”;
last_write_time 返回值怎么转成可读时间字符串
转换链比想象中长,因为 file_time_type 和系统时钟不在同一时区轨道上,必须经由 file_time_type::clock::to_sys 桥接:
auto ft = fs::last_write_time(path);
auto sys_tp = std::chrono::time_point_cast<std::chrono::seconds>(
fs::file_time_type::clock::to_sys(ft)
);
auto time_t_val = std::chrono::system_clock::to_time_t(sys_tp);
std::cout << std::put_time(std::localtime(&time_t_val), "%Y-%m-%d %H:%M:%S");
- 别漏掉
time_point_cast<seconds></seconds>,否则to_time_t可能截断毫秒级精度导致时间倒退 -
to_sys是 C++20 的新增要求,旧编译器(如 GCC __cpp_lib_filesystem - 如果只要 Unix 时间戳整数,直接用
sys_tp.time_since_epoch().count()
常见报错:filesystem error: No such file or directory
这不是代码写错了,而是路径没找对。尤其容易发生在相对路径、工作目录切换、打包后资源路径变化的场景:
- 用
fs::absolute(path)打印出来看看实际解析到哪了,比猜靠谱 - 如果路径含中文或特殊符号,确保源文件编码和运行环境 locale 一致(Windows 控制台默认 GBK,UTF-8 源码需
SetConsoleOutputCP(CP_UTF8)) - CMake 构建时,测试用例的工作目录默认是 build 目录,不是源码目录,
"./data/test.txt"很可能找不到
真正麻烦的从来不是函数怎么调,而是你手里的路径到底指哪儿——调试时先打一行 std::cout ,省掉八成问题。



















