C++如何获取文件的创建时间和修改时间_C++17标准库获取文件属性【手册】

2次阅读

c++17标准库std::Filesystem不支持获取文件创建时间,仅提供last_write_time和last_access_time;创建时间需依赖平台API:windows用GetFileTime,linux/macos无可靠跨平台方案。

C++如何获取文件的创建时间和修改时间_C++17标准库获取文件属性【手册】

std::filesystem::last_write_time 能拿到修改时间,但创建时间在 C++17 里没有标准支持

标准库 std::filesystem 在 C++17 中提供了跨平台的文件属性访问能力,但仅定义了 last_write_timelast_access_time没有 creation_time 的标准化接口。这意味着你用 std::filesystem::last_write_time(path) 可以可靠获取修改时间,但“创建时间”必须依赖平台扩展或系统 API。

常见错误是直接尝试调用不存在的 creation_time() 方法,编译器会报错:no member named 'creation_time' in Namespace 'std::filesystem'

  • std::filesystem::last_write_time(path) 返回 std::filesystem::file_time_type,需转换为 std::time_t 才能用 std::ctime 等格式化
  • windows 下可用 GetFileInformationByHandle 提取 ftCreationTime;Linux/macOS 没有真正意义上的“创建时间”,st_birthtimemacOS)或 st_crtime(某些 Linux 文件系统如 btrfs/xfs)是非标准、不可移植的扩展
  • 若项目要求跨平台且必须含创建时间,建议记录写入时的时间戳到元数据文件或数据库,而非依赖文件系统

把 file_time_type 转成可读时间字符串要经过两次转换

std::filesystem::file_time_type 是独立于 std::chrono::system_clock 的时钟类型,不能直接传给 std::gmtimestd::localtime。必须先转成 std::time_t,中间需借助 clock_cast(C++20)或手动换算(C++17)。

C++17 下典型做法是:先用 std::filesystem::file_time_type::clock::to_time_t(如果存在),但更稳妥的是通过 std::chrono::system_clock 中转:

立即学习C++免费学习笔记(深入)”;

auto ft = std::filesystem::last_write_time(path); auto sct = std::chrono::time_point_cast(     ft - ft.clock::now() + std::chrono::system_clock::now() ); std::time_t ctime = std::chrono::system_clock::to_time_t(sct);

这段代码容易出错:若文件时间早于 system_clock::now(),可能导致负偏移溢出;更健壮的做法是使用 Boost.Filesystem 或封装平台 API。

Windows 上用 GetFileTime 获取创建/修改/访问时间最直接

Windows API 的 GetFileTime 一次性返回三个时间戳,对应创建(lpCreationTime)、最后访问(lpLastAccessTime)、最后写入(lpLastWriteTime),精度达 100 纳秒,且稳定可用。

  • 需先用 CreateFile 打开句柄,注意设置 FILE_FLAG_BACKUP_SEMANTICS 才能打开目录
  • 返回的 FILETIME 是自 1601-01-01 的 100ns 计数,要用 FileTimeToSystemTimeFileTimeToLocalFileTime + FileTimeToSystemTime 转成本地可读结构
  • 记得关闭句柄,否则泄漏资源;INVALID_HANDLE_VALUEGetLastError() 是判断失败的关键

不推荐用 FindFirstFile,它只提供最后写入和最后访问时间,且对创建时间的支持在不同 Windows 版本中行为不一致。

Linux 下 st_birthtime 不是 POSIX 标准,别默认它存在

Linux 内核本身不维护“创建时间”,glibc 的 stat 结构体没有 st_birthtime 字段。某些文件系统(如 ext4)虽支持 btrfs ioctl(BTRFS_IOC_FS_INFO) 或 xfs 的 xfs_ioc_fsgeometry_v1,但用户态工具stat -c '%w' file 能显示“Birth”只是因为 coreutils 尝试读取扩展属性或特定 ioctl —— 这意味着:

  • 同一程序在 ext4 上可能读不到,在 btrfs 上却能读到,行为不可预测
  • statx(2) 系统调用(Linux 4.11+)提供了 statx.stx_btime,但需手动调用,且 glibc 尚未封装进 stat 函数
  • 即使读到,精度也常被截断为秒级,且部分内核配置会禁用 birthtime 支持

如果你看到某段 C++ 代码在 Linux 上调用了 st.st_birthtime 并成功运行,大概率是它链接了非标准补丁版 glibc,或运行在极少数启用 birthtime 的定制内核上 —— 这类代码不具备部署可靠性。

text=ZqhQzanResources