用GetFileTime获取Windows文件创建/访问时间必须先以GENERIC_READ权限调用CreateFile获取句柄,再经FileTimeToLocalFileTime和FileTimeToSystemTime两步转换才能得到本地可读时间;NTFS默认禁用最后访问时间更新,创建时间始终可用。

Windows下用GetFileTime获取创建/访问时间
Windows API 提供了 GetFileTime,这是最直接、无需第三方依赖的方式。它返回的是 FILETIME 结构(100纳秒精度的64位整数),必须转成本地可读时间。
常见错误是忽略时区转换或直接打印 FILETIME 值——结果全是大数字,毫无意义。
- 必须先用
CreateFile打开文件,且 flag 要含GENERIC_READ和FILE_SHARE_READ,否则GetFileTime失败返回 false - 调用后需用
FileTimeToLocalFileTime+FileTimeToSystemTime两步转换,跳过任意一步都会得到 UTC 时间或乱码 -
lpCreationTime对应创建时间,lpLastAccessTime是最后访问时间(注意:NTFS 默认禁用更新访问时间,除非关闭DisableLastAccessUpdate注册表项或格式化时禁用)
HANDLE h = CreateFile(L"test.txt", GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
FILETIME ftCreate, ftAccess;
if (GetFileTime(h, &ftCreate, nullptr, &ftAccess)) {
FILETIME localCreate, localAccess;
FileTimeToLocalFileTime(&ftCreate, &localCreate);
FileTimeToLocalFileTime(&ftAccess, &localAccess);
SYSTEMTIME st;
FileTimeToSystemTime(&localCreate, &st); // st now holds creation time
}
Linux/macOS用stat获取atime/mtime/ctime
POSIX 系统没有“创建时间”(birth time),stat 结构里的 st_ctime 是状态变更时间(如权限修改、重命名),不是 Windows 意义上的创建时间;st_atime 是最后访问时间,但默认挂载选项(relatime 或 noatime)可能不更新它。
实操中容易误把 st_ctime 当作创建时间,导致逻辑出错。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- Linux 从 4.11+ 内核开始支持
statx(),可取stx_btime(birth time),但需手动定义宏_GNU_SOURCE并检查statx返回值是否含STATX_BTIME标志 - macOS 的
stat有st_birthtime字段,但仅在 HFS+/APFS 上可靠,且需用stat -f "%B" file验证是否可用 - 跨平台代码若依赖创建时间,必须做运行时探测:先试
statx,fallback 到stat的st_ctime并加注释说明其非创建语义
跨平台方案:std::filesystem(C++17)只保证 last_write_time
std::filesystem::last_write_time() 是标准库唯一明确支持的时间戳,last_access_time() 和 creation_time() 完全未标准化——所有主流实现(libstdc++、libc++、MSVC STL)都不提供它们。
试图调用 std::filesystem::status("x").last_access_time() 会编译失败或静默返回 epoch 时间(1970-01-01)。
- 别依赖
std::filesystem获取 atime/ctime —— 标准没写,实现就不给 - 若必须跨平台,封装层需按 OS 分支:Windows 走
GetFileTime,Linux 走statx(带 fallback),macOS 走stat+st_birthtime - 注意
std::filesystem::file_time_type是基于系统时钟的 duration 类型,转time_t需用clock_cast(C++20)或手动换算,不能直接.time_since_epoch().count()
访问时间被禁用时怎么办
现代 Linux 默认启用 relatime(只在修改时间更新后才更新 atime),Windows 从 Vista 起也默认禁用 NTFS 访问时间更新。这意味着 st_atime 或 lpLastAccessTime 可能长期不变,甚至比 mtime 还旧。
这不是 bug,是性能优化。想强制更新,得主动 touch 文件或改挂载参数,但生产环境一般不允许。
- 不要用 atime 做“文件是否被读过”的判断依据,它不可靠
- 若业务真需要追踪访问,改用 inotify(Linux)或 ReadDirectoryChangesW(Windows)监听 open/read 事件
- 日志类场景建议记录应用层的 fopen/fread 时间,而非依赖文件系统元数据
创建时间在不同系统语义差异最大:Windows 有明确含义,Linux 大部分情况拿不到,macOS 有但不保证持久。拿不准时,先查 stat -c "%w %x %y" file(Linux)或 dir /T:C file(Windows)确认底层是否真存了这个值。

















