C++ 设置文件最近修改时间
利用VS开发C++项目,经常发现修改系统时间后,每次编译过程会变得很慢,其原因就是当你把系统时间调到未来的一个时间点,然后有意或者无意编辑过一些代码文件,那么这些文件的时间戳就停留在未来.
当你把系统时间调到现在后,编译器每次编译的时候,总会判定这些文件是最新的(因为它的时间戳总是大于目标文件的时间戳),所以总是会把这些文件编译一遍,如果这些文件中有某些被其他文件引用,那么会有更多的文件被重新编译,而且这种过程每次编译都会执行一遍,导致编译速度降低.为了解决这个问题,我特意写了一个小工具.
这个工具的原理跟简单,找出指定目录下时间戳大于当前时间的文件,并把它们的时间戳设置为现在时间.
调用的时候,配合一个bat脚本,把需要检查的代码目录传进去就好了,例如
echo off ResetFileTime MsgDefine Server pause
#include <io.h> #include <windows.h> #include <stdint.h> #include <vector> #include <string> #include <set> #include <stdio.h> #include <iostream> bool IsCompileFile(const std::string & extension) { static std::set<std::string> setComplieFileExtension = {".cpp", ".c", ".cc", ".h", ".hpp"}; return setComplieFileExtension.find(extension) != setComplieFileExtension.end(); } std::string GetFileNameExtension(const std::string & fileName) { /* DWORD dwAttrib = GetFileAttributes(fileName.c_str()); if (dwAttrib == INVALID_FILE_ATTRIBUTES) { return ""; } if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) { return ""; }*/ size_t dotpos = fileName.find_last_of("."); if(dotpos == std::string::npos) { return fileName; } return fileName.substr(dotpos, fileName.length() - dotpos); } bool CompareSystemTime(const SYSTEMTIME & lhs, const SYSTEMTIME & rhs) { if(lhs.wYear > rhs.wYear) { return true; } else if(lhs.wYear == rhs.wYear && lhs.wMonth > rhs.wMonth) { return true; } else if(lhs.wYear == rhs.wYear && lhs.wMonth == rhs.wMonth && lhs.wDay > rhs.wDay) { return true; } else if(lhs.wYear == rhs.wYear && lhs.wMonth == rhs.wMonth && lhs.wDay == rhs.wDay && lhs.wHour > rhs.wHour) { return true; } else if(lhs.wYear == rhs.wYear && lhs.wMonth == rhs.wMonth && lhs.wDay == rhs.wDay && lhs.wHour == rhs.wHour && lhs.wMinute > rhs.wMinute) { return true; } else if(lhs.wYear == rhs.wYear && lhs.wMonth == rhs.wMonth && lhs.wDay == rhs.wDay && lhs.wHour == rhs.wHour && lhs.wMinute == rhs.wMinute && lhs.wSecond > rhs.wSecond) { return true; } else if(lhs.wYear == rhs.wYear && lhs.wMonth == rhs.wMonth && lhs.wDay == rhs.wDay && lhs.wHour == rhs.wHour && lhs.wMinute == rhs.wMinute && lhs.wSecond == rhs.wSecond && lhs.wMilliseconds > rhs.wMilliseconds) { return true; } return false; } void DumpSystemTime(const std::string & prefix, const SYSTEMTIME & t) { printf("%s %04d-%02d-%02d %02d:%02d:%02d\n", prefix.c_str(), t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond); } void ResetFileTime(const std::string & dir) { WIN32_FIND_DATA fileInfo; HANDLE hFile = nullptr; char tmpPath[MAX_PATH] = { 0 }; sprintf_s(tmpPath, "%s\\*.*", dir.c_str()); if((hFile = FindFirstFile(tmpPath, &fileInfo)) == HANDLE(-1)) { return; } do { if(fileInfo.dwFileAttributes & _A_SUBDIR) { if(strcmp(fileInfo.cFileName, ".") == 0 || strcmp(fileInfo.cFileName, "..") == 0) { continue; } sprintf_s(tmpPath, "%s\\%s", dir.c_str(), fileInfo.cFileName); ResetFileTime(tmpPath); } else { sprintf_s(tmpPath, "%s\\%s", dir.c_str(), fileInfo.cFileName); std::string extension = GetFileNameExtension(fileInfo.cFileName); if(IsCompileFile(extension)) { FILETIME lastWriteLocalFileTime; FileTimeToLocalFileTime(&fileInfo.ftLastWriteTime, &lastWriteLocalFileTime); SYSTEMTIME lastWriteLocalSysTime, nowTime; FileTimeToSystemTime(&lastWriteLocalFileTime, &lastWriteLocalSysTime); GetLocalTime(&nowTime); if(CompareSystemTime(lastWriteLocalSysTime, nowTime)) { HANDLE file = ::CreateFile(tmpPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); DumpSystemTime(fileInfo.cFileName, lastWriteLocalSysTime); FILETIME nowWriteLocalFileTime; SystemTimeToFileTime(&nowTime, &nowWriteLocalFileTime); FILETIME nowWriteSysFileTime; LocalFileTimeToFileTime(&nowWriteLocalFileTime, &nowWriteSysFileTime); BOOL ret = SetFileTime(file, &nowWriteSysFileTime, &nowWriteSysFileTime, &nowWriteSysFileTime); if(ret == TRUE) { printf("reset time succ.\n"); } else { printf("reset time fail.error=%d\n", GetLastError()); } } } } } while(FindNextFile(hFile, &fileInfo) == TRUE); FindClose(hFile); } int32_t main(int32_t argc, char *argv[]) { for(int32_t i = 1; i < argc; ++i) { std::string dir = argv[i]; ResetFileTime(dir); } return 0; }