用getfiletime获取文件时间戳必须先以file_read_attributes权限调用createfile获取句柄,否则因权限不足返回error_access_denied;filetime需经filetimetolocalfiletime和filetimetosystemtime转换才能正确显示本地时间。

直接说结论:用 GetFileTime 是对的,但必须先用 CreateFile 以 FILE_READ_ATTRIBUTES 权限打开文件句柄,否则返回失败且 GetLastError() 是 ERROR_ACCESS_DENIED。
为什么 GetFileTime 总是失败?
最常见原因是权限不足。Windows 不允许通过路径名直接读取时间戳,必须先获取有效句柄。很多人用 GENERIC_READ 打开,但该权限不包含读取文件属性的权限——FILE_READ_ATTRIBUTES 才是专门为此设计的。
- 错误写法:
CreateFile(L"test.txt", GENERIC_READ, ...)→ 大概率失败 - 正确写法:
CreateFile(L"test.txt", FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, ..., OPEN_EXISTING, 0, nullptr) - 别漏掉
FILE_SHARE_DELETE:否则其他进程删除该文件时会阻塞你的句柄 - 调用后务必检查返回值是否为
INVALID_HANDLE_VALUE,再查GetLastError()
GetFileTime 返回的 FILETIME 怎么转成可读时间?
FILETIME 是自 1601-01-01 UTC 起的 100 纳秒计数,不能直接 printf。必须经 FileTimeToLocalFileTime + FileTimeToSystemTime 两步转换(注意顺序!先转本地时区,再转结构体)。
通过 SSH 隧道从 Android 设备在互联网上对 Windows PC 实现完整远程控制的设置与使用指南,适用于远程桌面访问、安全 RDP 等。
- 跳过
FileTimeToLocalFileTime→ 得到的是 UTC 时间,不是你系统显示的“创建时间” - 忘记初始化
SYSTEMTIME结构体 → 某些字段(如wMilliseconds)可能为随机值 - 示例关键片段:
FILETIME ftCreate, ftAccess, ftWrite; if (GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) { FILETIME ftLocal; SYSTEMTIME st; if (FileTimeToLocalFileTime(&ftCreate, &ftLocal) && FileTimeToSystemTime(&ftLocal, &st)) { wprintf(L"%04d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); } }
有没有更轻量、不需句柄的方式?
没有标准 API 可绕过句柄。但可以考虑 FindFirstFile / FindNextFile —— 它们在枚举时直接把创建时间放在 WIN32_FIND_DATA::ftCreationTime 里,省去单独调用 GetFileTime 的步骤。
- 适合批量获取(比如遍历目录),单个文件反而多此一举
-
FindFirstFile也需要路径通配符,单文件就写L"myfile.txt"即可 - 注意:返回的
ftCreationTime是 UTC 时间,仍需用FileTimeToLocalFileTime转换才匹配资源管理器显示 - 如果文件被重命名或移动,
FindFirstFile仍能拿到原时间;而GetFileTime对硬链接行为更明确
真正容易被忽略的是时区处理和权限粒度——FILE_READ_ATTRIBUTES 这个权限名太长,手误写成 FILE_ATTRIBUTE_READONLY 或漏掉,都会静默失败。还有人以为 GetFileTime 能读取符号链接目标的时间,其实它读的是链接本身(除非用 CREATE_OPEN_ALWAYS + FILE_FLAG_OPEN_REPARSE_POINT 配合 DeviceIoControl,那就完全是另一回事了)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










