C\C++ 日志记录


这是从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);//返回日期比较的结果
};




猜你喜欢

转载自blog.csdn.net/xuepiaofei1/article/details/79296567