如何获取目录的最后访问、修改时间戳?C++代码修复求助
修复Windows下C++获取目录时间戳的问题
你的代码在处理普通文件时正常,但处理目录时失效,核心原因是打开目录时没有使用Windows要求的特殊标志。Windows将目录视为特殊的文件对象,必须通过特定参数才能正确打开并读取其时间属性。
问题根源
调用CreateFileA打开目录时,默认参数无法识别目录对象,要么返回INVALID_HANDLE_VALUE,要么即便打开成功也无法读取时间戳。必须添加FILE_FLAG_BACKUP_SEMANTICS标志——这个标志允许系统将目录当作文件对象处理,从而支持后续的GetFileTime调用。
修复方案
修改CreateFileA的调用参数,添加必要的标志和共享权限:
- 新增
FILE_FLAG_BACKUP_SEMANTICS标志到创建参数 - 放宽共享权限为
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,避免因其他进程访问目录导致打开失败
另外,你的原函数GetLastWriteTimeDirectory仅返回最后写入时间,我把它扩展为支持同时获取创建、访问、写入三种时间戳,更贴合实际需求。
修改后的完整代码
#include <windows.h> #include <iostream> #include <stdio.h> #include <strsafe.h> #include <cstring> BOOL GetFileTimesDirectory(HANDLE arg_h_file, LPSTR arg_lpsz_create, DWORD arg_dw_size_create, LPSTR arg_lpsz_access, DWORD arg_dw_size_access, LPSTR arg_lpsz_write, DWORD arg_dw_size_write) { FILETIME ft_CreateTime, ft_AccessTime, ft_WriteTime; SYSTEMTIME st_UTC, st_Local; DWORD dw_Return; // 读取文件/目录的所有时间戳 if (!GetFileTime(arg_h_file, &ft_CreateTime, &ft_AccessTime, &ft_WriteTime)) { return FALSE; } // 转换创建时间为本地时间 FileTimeToSystemTime(&ft_CreateTime, &st_UTC); SystemTimeToTzSpecificLocalTime(NULL, &st_UTC, &st_Local); dw_Return = StringCchPrintfA(arg_lpsz_create, arg_dw_size_create, "%02d/%02d/%d %02d:%02d", st_Local.wMonth, st_Local.wDay, st_Local.wYear, st_Local.wHour, st_Local.wMinute); if (dw_Return != S_OK) return FALSE; // 转换访问时间为本地时间 FileTimeToSystemTime(&ft_AccessTime, &st_UTC); SystemTimeToTzSpecificLocalTime(NULL, &st_UTC, &st_Local); dw_Return = StringCchPrintfA(arg_lpsz_access, arg_dw_size_access, "%02d/%02d/%d %02d:%02d", st_Local.wMonth, st_Local.wDay, st_Local.wYear, st_Local.wHour, st_Local.wMinute); if (dw_Return != S_OK) return FALSE; // 转换写入时间为本地时间 FileTimeToSystemTime(&ft_WriteTime, &st_UTC); SystemTimeToTzSpecificLocalTime(NULL, &st_UTC, &st_Local); dw_Return = StringCchPrintfA(arg_lpsz_write, arg_dw_size_write, "%02d/%02d/%d %02d:%02d", st_Local.wMonth, st_Local.wDay, st_Local.wYear, st_Local.wHour, st_Local.wMinute); return (dw_Return == S_OK); } bool AttributeDirectoryTimes(const char* arg_path) { HANDLE handleFile; char bufferCreateTime[MAX_PATH]; char bufferAccessTime[MAX_PATH]; char bufferWriteTime[MAX_PATH]; char pathDirectory[MAX_PATH]; strcpy(pathDirectory, arg_path); // 修改CreateFileA参数,添加目录支持的标志和共享权限 handleFile = CreateFileA(pathDirectory, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (handleFile == INVALID_HANDLE_VALUE) { printf("打开目录失败,错误码:%lu\n", GetLastError()); // 新增错误排查信息 return false; } if (GetFileTimesDirectory(handleFile, bufferCreateTime, MAX_PATH, bufferAccessTime, MAX_PATH, bufferWriteTime, MAX_PATH)) { printf("\n\t\t创建时间: \t%s\n", bufferCreateTime); printf("\t\t访问时间: \t%s\n", bufferAccessTime); printf("\t\t写入时间: \t%s\n", bufferWriteTime); CloseHandle(handleFile); return true; } CloseHandle(handleFile); return false; } int main(int argc, char* argv[]) { AttributeDirectoryTimes("C:\\Users\\mkahs\\Desktop\\Sample\\"); return 0; }
关键修改点说明
CreateFileA参数调整:FILE_FLAG_BACKUP_SEMANTICS:让系统将目录识别为可操作的文件对象,这是处理目录的核心要求- 扩展共享权限:目录通常会被多个进程访问,使用
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE避免打开失败
- 函数扩展:将原单时间戳函数改为支持三种时间戳的函数,更实用
- 错误排查:添加
GetLastError()输出,方便调试打开目录失败的具体原因
额外高效方案
如果仅需要读取目录属性而不需要打开目录对象,也可以使用GetFileAttributesExA函数,代码会更简洁:
WIN32_FILE_ATTRIBUTE_DATA fileAttr; if (GetFileAttributesExA(arg_path, GetFileExInfoStandard, &fileAttr)) { // 直接使用fileAttr.ftCreationTime、fileAttr.ftLastAccessTime、fileAttr.ftLastWriteTime // 后续转换为本地时间的逻辑和之前一致 }
这种方式不需要调用CreateFileA,对于仅读取属性的场景效率更高。
内容的提问来源于stack exchange,提问作者user12317345
相关产品推荐
相关产品推荐

