c++oding="utf-8" ?>
Linux/macOS下std::filesystem不支持微秒级创建时间,需用statx(2)(Linux)或getattrlist(2)(macOS)获取纳秒级时间;Windows用GetFileInformationByHandle获100ns精度,除10得微秒。

Linux/macOS 下 stat 命令能看微秒,但 C++ 标准库不支持
标准 C++17 的 std::filesystem::last_write_time 只返回 file_time_type,底层通常是纳秒或 100ns 级精度(取决于平台),但 **不暴露微秒字段**,且无法直接获取创建时间(birth_time)——Linux 内核虽支持,但 glibc 长期未暴露该字段给用户态。
常见错误是以为 std::filesystem::file_time_type::time_since_epoch().count() 直接对应微秒:它返回的是平台原生时钟滴答数(如 Linux 上常为纳秒),单位不固定,硬除 1000 极易出错。
- Linux 上用
statx(2)系统调用才能可靠读取创建时间(stx_btime)和纳秒级时间戳 - macOS 上需用
getattrlist(2)或stat64(2)+st_birthtimespec字段 - Windows 下
GetFileInformationByHandle返回的FILETIME是 100ns 单位,可直接转微秒(除以 10)
Linux:用 statx 读取纳秒级 birth/access/modify 时间
statx 是 Linux 4.11+ 引入的系统调用,唯一能跨文件系统稳定获取创建时间(stx_btime)并带纳秒精度的接口。glibc 2.28+ 才封装了 statx(2),旧版本得手写 syscall。
关键点:必须传 AT_STATX_SYNC_AS_STAT 标志,否则某些文件系统(如 ext4)可能返回不精确值;stx_btime.tv_nsec 是纳秒部分,不是微秒——要转微秒得除以 1000 并截断(非四舍五入)。
#include <sys>
#include <linux>
// ... 检查内核/glibc 版本后调用
struct statx stx;
if (statx(AT_FDCWD, "/path/to/file", AT_SYMLINK_NOFOLLOW,
STATX_BTIME | STATX_MTIME | STATX_ATIME, &stx) == 0) {
auto btime_us = stx.stx_btime.tv_sec * 1000000LL + stx.stx_btime.tv_nsec / 1000;
auto mtime_us = stx.stx_mtime.tv_sec * 1000000LL + stx.stx_mtime.tv_nsec / 1000;
auto atime_us = stx.stx_atime.tv_sec * 1000000LL + stx.stx_atime.tv_nsec / 1000;
}
</linux></sys>
Windows:用 GetFileInformationByHandle 提取 100ns 级时间
Windows 的 FILETIME 是自 1601-01-01 起的 100ns 计数,直接转微秒只需除以 10。注意:ftCreationTime 是创建时间,ftLastWriteTime 是修改时间,ftLastAccessTime 是访问时间(NTFS 默认禁用更新访问时间,注册表键 HKLM\SYSTEM\CurrentControlSet\Control\Filesystem\NtfsDisableLastAccessUpdate 控制)。
容易踩的坑:直接用 FILETIME 结构体赋值会因字节序或对齐出错;必须用 ULARGE_INTEGER 联合体安全读取 64 位值。
HANDLE h = CreateFile(L"file.txt", GENERIC_READ, FILE_SHARE_READ, nullptr,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
BY_HANDLE_FILE_INFORMATION info;
if (GetFileInformationByHandle(h, &info)) {
ULARGE_INTEGER c, m, a;
c.LowPart = info.ftCreationTime.dwLowDateTime;
c.HighPart = info.ftCreationTime.dwHighDateTime;
m.LowPart = info.ftLastWriteTime.dwLowDateTime;
m.HighPart = info.ftLastWriteTime.dwHighDateTime;
a.LowPart = info.ftLastAccessTime.dwLowDateTime;
a.HighPart = info.ftLastAccessTime.dwHighDateTime;
auto c_us = c.QuadPart / 10; // 100ns → μs
auto m_us = m.QuadPart / 10;
auto a_us = a.QuadPart / 10;
}
跨平台封装时,别信 std::filesystem 的“创建时间”假象
某些编译器(如 GCC 13+)在 Linux 上尝试用 statx 补充 std::filesystem::creation_time,但行为不一致:Clang/libc++ 完全不实现,MSVC 在 Windows 上返回 FILETIME 但没公开精度说明。更麻烦的是,即使函数存在,返回类型仍是 file_time_type,你仍需自己解析其内部计数值——而各 STL 实现的 epoch 和 tick 单位不同(libstdc++ 用 Unix epoch,libc++ 用 Windows epoch)。
- 不要依赖
std::filesystem::creation_time,它在 Linux/macOS 上多数情况抛std::filesystem::filesystem_error - 若必须跨平台,优先按 OS 分支手写系统调用,而非包装 STL 接口
- 微秒级时间戳用于日志或调试足够,但做文件变更比对时,注意 FAT32 创建时间只有 2 秒精度,exFAT 是 10ms,别拿微秒值当绝对依据
真正难的不是拿到微秒数字,而是搞清每个平台、每个文件系统、每个内核版本到底存了什么精度的时间——同一行代码在 ext4 和 XFS 上,statx 返回的 tv_nsec 可能一个是 0,一个是 123456789。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











