背景
在某些特定场景下,会有修改文件创建时间、修改时间的需求。具体为什么要修改文件时间就不去纠结了,感兴趣的可以去做个问卷调查,也可以自行脑补,反正经常有小伙伴问怎么去修改文件时间。
最简单的解决方案
文件的时间作为文件的属性,当然是由文件的编辑工具生成或修改的。那么最简单的方式就是把你的系统时间设置为想要改的时间点,比如设置为2000年1月1日的某个时间点,然后打开文件编辑工具,随便修改点内容,比如在某个位置敲一个字符然后删除并保存,虽然文件的内容没变,但是文件的修改时间已经变为2000年1月1日。然而你会发现,文件的创建时间没有更改,所以你需要将文件另存为某个文件,你就会发现另存为的文件的创建时间变成了你想要的时间。这个时候你就可以拿这个另存为的文件去交差了,一切很简单。
缺点
1、修改系统时间很简单,但是总是不想改,嫌麻烦。
2、需要修改或另存为文件,批量修改文件时间不被累死就被烦死。
3、有些文件压根就找不到对应的编辑工具,谈何修改或另存为。
4、太低效。
最简单高效的解决方案
最简单高效的方式,当然是调用系统接口,直接修改文件时间为自己指定的时间。
原理
在windows系统中,修改文件的时间属性一般都是调用API直接修改,C/C++ API如下:
BOOL SetFileTime(
HANDLE hFile,
CONST FILETIME *lpCreationTime,
CONST FILETIME *lpLastAccessTime,
CONST FILETIME *lpLastWriteTime
);
详细的API说明在微软官方文档页面上有介绍,可以自行到微软官方文档页面进行搜索查询。
实现Demo
以下采用C语言实现,以便参考,读者可以采用自己擅长的语言自行实现。
#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
int main(int argc, char *argv[]) {
// 传参格式: 可执行程序.exe fileName time
// 传参示例:App.exe test.txt 2018-09-04 20:28:50
// 参数检查
if( argc != 4 ) {
printf("Use format: %s fileName time\nUse like: %s test.txt 2018-09-04 20:28:50\n", argv[0], argv[0]);
return -1;
}
// 检查时间格式
if( strlen(argv[2]) != 10 || strlen(argv[3]) != 8 ) {
printf("Time format is invalid, time format like: 2018-09-04 20:28:50\n");
return -1;
}
// 读取指定时间
SYSTEMTIME spec_time;
sscanf(argv[2],"%d-%d-%d", &spec_time.wYear, &spec_time.wMonth, &spec_time.wDay);
sscanf(argv[3],"%d:%d:%d", &spec_time.wHour, &spec_time.wMinute, &spec_time.wSecond);
spec_time.wDayOfWeek = 1;
spec_time.wMilliseconds = 0;
// TODO: 此处省略对时间有效性的校验
// 获取文件句柄
HANDLE hFile = CreateFile(argv[1], // LPCTSTR lpFileName,
GENERIC_READ|GENERIC_WRITE, // DWORD dwDesiredAccess,
FILE_SHARE_READ|FILE_SHARE_DELETE,
NULL, // LPSECURITY_ATTRIBUTES lpSecurityAttributes,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, // DWORD dwFlagsAndAttributes,
NULL);
if( hFile == INVALID_HANDLE_VALUE ) {
printf("Get file handle failed, error = %s\n", GetLastError());
return -1;
}
// 设置文件时间
FILETIME ft,LocalFileTime;
SystemTimeToFileTime(&spec_time, &ft);
LocalFileTimeToFileTime(&ft,&LocalFileTime);
if(SetFileTime(hFile,&LocalFileTime,(LPFILETIME) NULL,&LocalFileTime)) {
printf("Set file time success\n");
}else{
printf("Set file time failed\n");
}
CloseHandle(hFile);
return 0;
}