这是从csdn问答里看到的,是赵四老师的。找不到链接了。在此基础上做了一些修改。
这里可以定义清除多少天前的日志。
cpp:
#include "stdafx.h"
#include "WriteLog.h"
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#include <io.h>
#else
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#define CRITICAL_SECTION pthread_mutex_t
#define _vsnprintf vsnprintf
#endif
CWriteLog::CWriteLog()
{
#ifdef WIN32
InitializeCriticalSection(&cs_log);
#else
pthread_mutex_init(&cs_log, NULL);
#endif
}
CWriteLog::~CWriteLog()
{
#ifdef WIN32
DeleteCriticalSection(&cs_log);
#else
pthread_mutex_destroy(&cs_log);
#endif
}
//Log{
char logfilename1[] = "MyLog1.log";
char logfilename2[] = "MyLog2.log";
#ifdef WIN32
std::string CWriteLog::GetExePath()
{
char szapipath[MAX_PATH];//(D:\Documents\Downloads\TEST.exe)
memset(szapipath, 0, MAX_PATH);
GetModuleFileNameA(NULL, szapipath, MAX_PATH);
string strPath = szapipath;
int nPos = strPath.rfind("\\");
string strRet = strPath.substr(0, nPos) + "\\";
return strRet;
}
void CWriteLog::Lock(CRITICAL_SECTION *cs)
{
EnterCriticalSection(cs);
}
void CWriteLog::Unlock(CRITICAL_SECTION *cs)
{
LeaveCriticalSection(cs);
}
#else
void CWriteLog::Lock(CRITICAL_SECTION *l)
{
pthread_mutex_lock(l);
}
void CWriteLog::Unlock(CRITICAL_SECTION *l)
{
pthread_mutex_unlock(l);
}
#endif
void CWriteLog::Log2File(const char *pszFmt, va_list argp) {
struct tm *now;
struct timeb tb;
char datestr[16] = {0};
char timestr[16] = { 0 };
char mss[4] = { 0 };
char logstr[MAXLINSIZE + 1] = {0};
FILE *flog = NULL;
try
{
if (NULL == pszFmt || 0 == pszFmt[0]) return;
_vsnprintf(logstr, MAXLINSIZE, pszFmt, argp);
ftime(&tb);
now = localtime(&tb.time);
sprintf(datestr, "%04d-%02d-%02d", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);
sprintf(timestr, "%02d:%02d:%02d", now->tm_hour, now->tm_min, now->tm_sec);
sprintf(mss, "%03d", tb.millitm);
//printf("%s %s.%s %s", datestr, timestr, mss, logstr);
string strLogFileName = GetExePath();
strLogFileName += datestr;
strLogFileName += "_Demo.log";
flog = fopen(strLogFileName.c_str(), "ab+");
if (NULL != flog)
{
fprintf(flog, "%s %s.%s %s", datestr, timestr, mss, logstr);
ClearLog(DeleteLogDays, strLogFileName);
fclose(flog);
/*
if (ftell(flog) > MAXLOGSIZE)
{
fclose(flog);
if (rename(logfilename1, logfilename2))
{
remove(logfilename2);
rename(logfilename1, logfilename2);
}
}
else
{
fclose(flog);
}
*/
}
}
catch (...)
{
if (flog != NULL)
{
fclose(flog);
}
}
}
void CWriteLog::Log(const char *pszFmt, ...) {
va_list argp;
Lock(&cs_log);
va_start(argp, pszFmt);
Log2File(pszFmt, argp);
va_end(argp);
Unlock(&cs_log);
}
// 功能:删除nDays天及之前的日志文件
// @nDays: 0-不删除日志,3-删除3天及之前的日志(保留今天、昨天、前天的日志) ...
void CWriteLog::ClearLog(UINT nDays, string strPath) // 删除N天前的日志
{
if (nDays > 0)
{
WIN32_FIND_DATAA FindFileData;
char szFileName[MAX_PATH] = { 0 };
strcpy(szFileName, strPath.c_str());
strcat(szFileName, "*.log");
string m_sLogFolder = strPath;
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 CWriteLog::IsLeapYear(int year)
{
return ((year % 4 == 0) && (year % 100 != 0) || year % 400 == 0);
}
//得到date.month的最大天数
int CWriteLog::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 CWriteLog::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 CWriteLog::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 CWriteLog::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 CWriteLog::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:
#pragma once
#include <string>
using namespace std;
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#define DeleteLogDays 10 //删除多久前的日志
struct tagDate
{
int year;
int month;
int day;
};
class CWriteLog
{
public:
CWriteLog();
~CWriteLog();
public:
void Log(const char *pszFmt, ...);
private:
CRITICAL_SECTION cs_log;
private:
string GetExePath();
void Lock(CRITICAL_SECTION *cs);
void Unlock(CRITICAL_SECTION *cs);
void Log2File(const char *pszFmt, va_list argp);
void ClearLog(UINT nDays, string strPath); // 删除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);//返回日期比较的结果
};