这是从csdn问答里看到的,是赵四老师的。找不到链接了。在此基础上做了一些修改。
这里可以定义清除多少天前的日志。
cpp:
#include "EParkingLog.h"
#include <corecrt_io.h>
#define MaxJsonBuffer 1024
CEParkingLog::CEParkingLog(char* pLogFileName)
{
memset(m_szFileFlag, 0, sizeof(m_szFileFlag));
if (pLogFileName != NULL)
{
memcpy(m_szFileFlag, pLogFileName, strlen(pLogFileName));
}
day = -1;
changefile = 0;
fp = NULL;
m_Check = 0;
m_Seq = 0;
m_Temp = 0;
string strTemp = GetLocalAppDataPath("EParking\\EParkingManage\\log\\");
string strPath = strTemp;
strcpy(file_name, strPath.c_str());
_mkdir(file_name);
name_len = strlen(file_name);
ClearLog(15);
InitializeCriticalSection(&m_LockInfo);
InitializeCriticalSection(&m_LockCheck);
InitializeCriticalSection(&m_LockSeq);
InitializeCriticalSection(&m_LockTemp);
}
CEParkingLog::~CEParkingLog(void)
{
}
int CEParkingLog::WriteLogFile(const char *fmt,...)
{
if (strlen(fmt) > MaxJsonBuffer - MAX_PATH)
{
return 0;
}
unsigned long res = 0;
char *pLoginfo = new char[MaxJsonBuffer];
char name[4096] = {0};
// time_t tm;
// struct tm *p_tm;
SYSTEMTIME systi;
GetLocalTime(&systi);
va_list ap;
memset(pLoginfo,0x00,MaxJsonBuffer);
memset(name,0x00,sizeof(name));
//取得当前时间
//time(&tm);
//p_tm = localtime(&tm);
//取得文件名
sprintf(name,"%s%04d-%02d-%02d %s.log",file_name, systi.wYear, systi.wMonth, systi.wDay,/*p_tm->tm_year+1900,p_tm->tm_mon+1,p_tm->tm_mday,*/ m_szFileFlag);
if (day != systi.wDay/*p_tm->tm_mday*/)
{
day = systi.wDay/*p_tm->tm_mday*/;
changefile = 1;
if (fp != NULL)
{
fclose(fp);
fp = NULL;
}
}
//生成日志信息
sprintf(pLoginfo, "[%04d-%02d-%02d %02d:%02d:%02d %3d]:", systi.wYear, systi.wMonth, systi.wDay, systi.wHour, systi.wMinute, systi.wSecond, systi.wMilliseconds); /*p_tm->tm_year + 1900, p_tm->tm_mon + 1, p_tm->tm_mday, p_tm->tm_hour,p_tm->tm_min,p_tm->tm_sec*/
va_start(ap,fmt);
vsprintf(pLoginfo+strlen(pLoginfo),fmt,ap);
va_end(ap);
//打开文件开始写
EnterCriticalSection(&m_LockInfo);
if (fp == NULL || changefile == 1)
{
fp = fopen(name,"a+");
if (fp == NULL)
{
LeaveCriticalSection(&m_LockInfo);
if (pLoginfo != NULL)
{
delete[] pLoginfo;
pLoginfo = NULL;
}
return 0;
}
changefile = 0;
}
fwrite(pLoginfo,strlen(pLoginfo),1,fp);
fwrite("\n", 1, 1, fp);
fflush(fp); //刷新
res = ftell(fp);//用于得到文件当前位置相对于文件首的偏移字节数
if (res > 30000000)
{
fclose(fp);
fp = NULL;
changefile = 1;
}
LeaveCriticalSection(&m_LockInfo);
if (pLoginfo != NULL)
{
delete[] pLoginfo;
pLoginfo = NULL;
}
return 1;
}
unsigned long CEParkingLog::WriteCheck()
{
EnterCriticalSection(&m_LockCheck);
m_Check++;
LeaveCriticalSection(&m_LockCheck);
return m_Check;
}
unsigned long CEParkingLog::WriteSeq()
{
EnterCriticalSection(&m_LockSeq);
m_Seq++;
LeaveCriticalSection(&m_LockSeq);
return m_Seq;
}
unsigned long CEParkingLog::WriteTemp()
{
EnterCriticalSection(&m_LockTemp);
m_Temp++;
LeaveCriticalSection(&m_LockTemp);
return m_Temp;
}
std::string CEParkingLog::GetLocalAppDataPath()
{
char m_lpszDefaultDir[MAX_PATH];
char szDocument[MAX_PATH] = {0};
memset(m_lpszDefaultDir, 0, _MAX_PATH);
LPITEMIDLIST pidl = NULL;
SHGetSpecialFolderLocation(NULL, CSIDL_LOCAL_APPDATA, &pidl);
if (pidl && SHGetPathFromIDListA(pidl, szDocument))
{
GetShortPathNameA(szDocument,m_lpszDefaultDir, _MAX_PATH);
}
std::string wsR = m_lpszDefaultDir;
return wsR;
}
std::string CEParkingLog::GetLocalAppDataPath(std::string appName)
{
std::string path = GetLocalAppDataPath();
path.append("\\");
path.append(appName);
if ( _access(path.c_str(), 0) == -1 )
{
_mkdir(path.c_str());
}
return path;
}
// 功能:删除nDays天及之前的日志文件
// @nDays: 0-不删除日志,3-删除3天及之前的日志(保留今天、昨天、前天的日志) ...
void CEParkingLog::ClearLog(UINT nDays) // 删除N天前的日志
{
if (nDays > 0)
{
WIN32_FIND_DATAA FindFileData;
char szFileName[512] = { 0 };
strcpy(szFileName, file_name);
strcat(szFileName, "*.log");
string m_sLogFolder = file_name;
HANDLE hFind = ::FindFirstFileA(szFileName, &FindFileData);
if (INVALID_HANDLE_VALUE == hFind) return;
while (TRUE)
{
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) // 遇到文件夹
{
}
else // 遇到文件
{
try
{
string sFileName = FindFileData.cFileName;
//sFileName.Format("%s", FindFileData.cFileName);
if (sFileName.length() == 14)
{
string sFileFullPath = m_sLogFolder + "\\" + sFileName;// 文件全路径
//sFileName.replace("-", "");
int nFileName = atoi(sFileName.c_str()); // 取得文件的日期,如:20101030
SYSTEMTIME systi;
GetLocalTime(&systi);
tagDate dtBegin;
tagDate dtEnd;
dtBegin.year = atoi(sFileName.substr(0, 4).c_str());
dtBegin.month = atoi(sFileName.substr(5, 2).c_str());
dtBegin.day = atoi(sFileName.substr(8, 2).c_str());
dtEnd.year = systi.wYear;
dtEnd.month = systi.wMonth;
dtEnd.day = systi.wDay;
//CTime tNowTime = CTime::GetCurrentTime();
//tNowTime = tNowTime - CTimeSpan(nDays, 0, 0, 0); // 指向nDays天前的日期
//__int64 nNowTime = _atoi64(tNowTime.Format("%Y%m%d"));
if (DateDiff(dtBegin, dtEnd) > nDays)
{
::DeleteFileA(sFileFullPath.c_str());
}
}
}
catch (exception ex)
{
//printf("删除超过15天的日志模块出错\n");
}
}
if (!FindNextFileA(hFind, &FindFileData))
break;
}
FindClose(hFind);
}
}
//是否闰年
int CEParkingLog::IsLeapYear(int year)
{
return ((year % 4 == 0) && (year % 100 != 0) || year % 400 == 0);
}
//得到date.month的最大天数
int CEParkingLog::GetLastDay(tagDate date)
{
int num;
switch (date.month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
num = 31;
break;
case 2:
num = 28 + IsLeapYear(date.year);
break;
default:
num = 30;
}
return num;
}
//日期是否合法
int CEParkingLog::IsDateValid(tagDate date)
{
if (date.year < 0 || date.month < 1 || date.month> 12)
return 0;
if (date.day <1 || date.day> GetLastDay(date))
return 0;
return 1;
}
//date+1
void CEParkingLog::AddDay(tagDate *date)
{
date->day++;
if (date->day > GetLastDay(*date))
{
date->day = 1;
date->month++;
if (date->month > 12)
{
date->month = 1;
date->year++;
}
}
}
//date1比date2小返回值为1,否则为0
int CEParkingLog::Compare(tagDate date1, tagDate date2)
{
if (date1.year < date2.year)
return 1;
if (date1.year <= date2.year && date1.month < date2.month)
return 1;
if (date1.year <= date2.year && date1.month <= date2.month && date1.day < date2.day)
return 1;
return 0;
}
//计算两个日期的间隔天数
long CEParkingLog::DateDiff(tagDate date1, tagDate date2)
{
long delta = 0;
tagDate date3;
//若date1 > date2,交换date1,date2
if (!Compare(date1, date2))
{
date3 = date2;
date2 = date1;
date1 = date3;
}
//date1比date2少时,date1日期加1
while (Compare(date1, date2))
{
AddDay(&date1);
delta++;
}
return delta;
}
.h:
/*
功能:日志记录
日志目录:在APPData\\local\\EParking\\EParkingManage\\log\\2017-01-01.log
程序每次启动时,检测日志目录中日志文件的日期,如果是15天前的日志,则删除。
*/
#pragma once
#ifndef _CLASS_EPARKING_LOG_H_
#define _CLASS_EPARKING_LOG_H_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <time.h>
#include <direct.h>
#include <string>
#include <Shlobj.h>
#pragma comment( lib, "shell32.lib")
using namespace std;
struct tagDate
{
int year;
int month;
int day;
};
class CEParkingLog
{
public:
CEParkingLog(char* pLogFileName);//在日期后面的标志,如2017-09-18 server.log
public:
~CEParkingLog(void);
int WriteLogFile(const char *fmt,...);
unsigned long WriteCheck();
unsigned long WriteSeq();
unsigned long WriteTemp();
private:
char file_name[256];
FILE *fp;
int name_len;
unsigned long m_Check ;
unsigned long m_Seq ;
unsigned long m_Temp;
int day;
int changefile;
char m_szFileFlag[20];
CRITICAL_SECTION m_LockInfo;
CRITICAL_SECTION m_LockCheck;
CRITICAL_SECTION m_LockSeq;
CRITICAL_SECTION m_LockTemp;
private:
//获取appdata目录
std::string GetLocalAppDataPath();
std::string GetLocalAppDataPath(std::string appName);
void ClearLog(UINT nDays); // 删除N天前的日志;
//以下是日期比较,根据是文件名上的日期和当前系统日期
int IsLeapYear(int year);//闰年
int GetLastDay(tagDate date);
int IsDateValid(tagDate date);
void AddDay(tagDate *date);
int Compare(tagDate date1, tagDate date2);
long DateDiff(tagDate date1, tagDate date2);//返回日期比较的结果
};
#endif //_CLASS_LOG_MY