C++实现一个简洁而又强大的日志记录类

代码执行时记录日志是很有必要的,尤其在涉及到多进程、多线程调试或者是调试服务程序时。本分分享一个最近写的简单的日志类,希望有所帮助。不喜欢废话,上代码了:

头文件如下:

#pragma once
#include <string>
using std::string;
using std::wstring;

class CSimpleLog
{
public:
	CSimpleLog(void);
	~CSimpleLog(void);
	void	Write(const char* pSourcePath, const char* pFunName, const long lLine, const char* pLogText);
	void	Write(const char* pSourcePath, const char* pFunName, const long lLine, const wchar_t* pLogText);
	void	ScanfWrite(const char* pSourcePath, const char* pFunName, const long lLine, \
		const char* pLogText, ...);
	void	ScanfWrite(const char* pSourcePath, const char* pFunName, const long lLine, \
		const wchar_t* pLogText, ...);
protected:
	string	GetTime();
	string	U2A(const wstring& str);
};

extern CSimpleLog	g_log;

#define SL_LOG(x)				g_log.Write(__FILE__, __FUNCTION__, __LINE__, x)
#define SL_LOG1(x, p1)			g_log.ScanfWrite(__FILE__, __FUNCTION__, __LINE__, x, p1)
#define SL_LOG2(x, p1, p2)		g_log.ScanfWrite(__FILE__, __FUNCTION__, __LINE__, x, p1, p2)
#define SL_LOG3(x, p1, p2, p3)	g_log.ScanfWrite(__FILE__, __FUNCTION__, __LINE__, x, p1, p2, p3)

实现文件:

 

 

#include "StdAfx.h"
#include "SimpleLog.h"
#include <Windows.h>

CSimpleLog	g_log;
const char* g_pLogPath="c:\\simple.log";
CSimpleLog::CSimpleLog(void)
{
}

CSimpleLog::~CSimpleLog(void)
{
}

void CSimpleLog::Write( const char* pSourcePath, const char* pFunName, \
					   const long lLine, const char* pLogText )
{
	if ( pLogText == NULL )
		return ;
	int nLogLen=strlen(pLogText);
	if ( nLogLen == 0 )
		return ;
	int nSourceLen=strlen(pSourcePath);
	int nFunLen	=strlen(pFunName);
	char szLine[10]={0};
	sprintf_s(szLine, "%ld", lLine);
	int nLineLen=strlen(szLine);
	int nSpaceLen=80-nSourceLen-nFunLen-nLineLen;
	string strTime=GetTime();
	FILE* fp=NULL;
	fopen_s(&fp, g_pLogPath, "a+");
	fwrite(strTime.c_str(), strTime.size(), 1, fp);
	fwrite(" ", 1, 1, fp);
	fwrite(pSourcePath, nSourceLen, 1, fp);
	for (int i=0; i<nSpaceLen; ++i )
		fwrite(" ", 1, 1, fp);
	fwrite(pFunName, nFunLen, 1, fp);
	fwrite(" ", 1, 1, fp);
	fwrite(szLine, nLineLen, 1, fp);
	fwrite(": ", 2, 1, fp);
	fwrite(pLogText, nLogLen, 1, fp);
	fwrite("\n", 1, 1, fp);
	fclose(fp);
}

void CSimpleLog::Write( const char* pSourcePath, const char* pFunName, const long lLine, const wchar_t* pLogText )
{
	string strLogText=U2A(pLogText);
	Write(pSourcePath, pFunName, lLine, strLogText.c_str());
}

string CSimpleLog::GetTime()
{
	SYSTEMTIME st;
	::GetLocalTime(&st);
	char szTime[26]={0};
	sprintf_s(szTime, "%04d-%02d-%02d %02d:%02d:%02d %d  ", st.wYear, st.wMonth, st.wDay, st.wHour, \
		st.wMinute, st.wSecond, st.wMilliseconds);
	return szTime;
}

string CSimpleLog::U2A(const wstring& str)
{
	string strDes;
	if ( str.empty() )
		goto __end;
	int nLen=::WideCharToMultiByte(CP_ACP, 0, str.c_str(), str.size(), NULL, 0, NULL, NULL);
	if ( 0==nLen )
		goto __end;
	char* pBuffer=new char[nLen+1];
	memset(pBuffer, 0, nLen+1);
	::WideCharToMultiByte(CP_ACP, 0, str.c_str(), str.size(), pBuffer, nLen, NULL, NULL);
	pBuffer[nLen]='\0';
	strDes.append(pBuffer);
	delete[] pBuffer;
__end:
	return strDes;
}

void CSimpleLog::ScanfWrite( const char* pSourcePath, const char* pFunName, const long lLine, \
							const char* pLogText, ... )
{
	va_list pArgs;
	va_start(pArgs, pLogText);
	char szBuffer[1024]={0};
	_vsnprintf_s(szBuffer, 1024, pLogText, pArgs);
	va_end(pArgs);
	Write(pSourcePath, pFunName, lLine, szBuffer);
}

void CSimpleLog::ScanfWrite( const char* pSourcePath, const char* pFunName, const long lLine, \
							const wchar_t* pLogText, ... )
{
	va_list pArgs;
	va_start(pArgs, pLogText);
	wchar_t szBuffer[1024]={0};
	_vsnwprintf_s(szBuffer, 1024, pLogText, pArgs);
	va_end(pArgs);
	Write(pSourcePath, pFunName, lLine, szBuffer);
}


这里把日志记录目录固定了,你也可以扩展下,提供一个设置保存路径的接口,或者是日志到了多大就换个文件来存储之类的。

 

如何使用?

你只需要在需要记录日志的地方加上宏:

SL_LOG
<pre name="code" class="cpp">SL_LOG1
SL_LOG3
1,2,3分别表示的是参数的个数,至于参数的类型和C语言格式化输出一样的。

日志输出结果包含:时间、文件名、函数名、日志内容。

 

 

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值