1 背景
实际项目中经常遇到需要将程序产生的“垃圾文件”定期进行删除,避免占用储存空间。诸如程序输出的日志文件、缩略图、缓存影片数据等。
2 情景
这里假设一种情景:某大型软件在实际生产过程中,会产生日志文件到指定的日志存放路径log下,并且产生日志的文件后缀为.log,需要程序检查此目录下创建时间超过指定期限的过期文件。
3 实现
- 开发环境:Visual Studio 2013
- 字符集:使用Unicode字符集
实现方式有很多种,这里使用多线程的方式来实现。
3.1 头文件
包含_beginthreadex()使用的头文件和std::string使用的头文件。
#include <process.h>
#include <string>
声明
public:
static unsigned int WINAPI DeleteExpireDirectoryThread(LPVOID lpvoid);
private:
std::string savePath;
int saveDays;
3.2 源文件
创建线程
HANDLE hDelDirHand;
hDelDirHand = (HANDLE)_beginthreadex(NULL, 0, DeleteExpireDirectoryThread, this, 0, NULL);
CloseHandle(hDelDirHand);
线程操作
unsigned int WINAPI AppLogging::DeleteExpireDirectoryThread(LPVOID lpvoid)
{
AppLogging* pThis = (AppLogging*)lpvoid;
int nDays = pThis->saveDays;
std::string logPath = pThis->savePath;
while (1)
{
WIN32_FIND_DATAA findData;
ZeroMemory(&findData, sizeof(WIN32_FIND_DATAA));
HANDLE hError;
char FilePathName[255];
std::string logPathAll = logPath + "\\*.*";
hError = FindFirstFileA(logPathAll.c_str(), (LPWIN32_FIND_DATAA)&findData);
if (hError == INVALID_HANDLE_VALUE)
{
Sleep(5000);
continue;
}
while (::FindNextFileA(hError, (LPWIN32_FIND_DATAA)&findData))
{
// 过虑.和..
if (strcmp(findData.cFileName, ".") == 0
|| strcmp(findData.cFileName, "..") == 0)
{
continue;
}
std::string tempFileName = findData.cFileName;
std::size_t found = tempFileName.find(".log");
if (found == std::string::npos) //不是日志文件
{
continue;
}
tempFileName = logPath + "\\" + tempFileName;
FILETIME ftCreate, ftModify, ftAccess;
std::string strCreateTime, strModifyTime, strAccessTime;
HANDLE hFile = CreateFileA(tempFileName.c_str(), GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_FLAG_BACKUP_SEMANTICS, // normal file
NULL);
if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftModify))
{
CloseHandle(hFile);
continue;
}
CloseHandle(hFile);
//文件时间转为系统时间
SYSTEMTIME createTime;
ZeroMemory(&createTime, sizeof(SYSTEMTIME));
FileTimeToSystemTime(&ftCreate, &createTime);
//获取当前时间
SYSTEMTIME stSystem;
::GetSystemTime(&stSystem);
int diffDays = GetDiffDays(createTime, stSystem);
if (GetDiffDays(createTime, stSystem) > nDays) //该日志文件过期
{
DeleteFileA(tempFileName.c_str()); //删除过期日志文件
}
}
Sleep(10000);
}
return 0;
}
时间大小比较
time_t FileTimeToTime_t(const FILETIME &ft)
{
ULARGE_INTEGER ui;
ui.LowPart = ft.dwLowDateTime;
ui.HighPart = ft.dwHighDateTime;
return ((LONGLONG)(ui.QuadPart - 116444736000000000) / 10000000);
}
int GetDiffSeconds(const SYSTEMTIME &t1, const SYSTEMTIME &t2)
{
FILETIME fTime1 = { 0, 0 };
FILETIME fTime2 = { 0, 0 };
SystemTimeToFileTime(&t1, &fTime1);
SystemTimeToFileTime(&t2, &fTime2);
time_t tt1 = FileTimeToTime_t(fTime1);
time_t tt2 = FileTimeToTime_t(fTime2);
return (int)(tt2 - tt1);
}
int GetDiffDays(const SYSTEMTIME &t1, const SYSTEMTIME &t2)
{
int diffSeconds = GetDiffSeconds(t1, t2);
return diffSeconds / (24 * 3600);
}