代码执行时记录日志是很有必要的,尤其在涉及到多进程、多线程调试或者是调试服务程序时。本分分享一个最近写的简单的日志类,希望有所帮助。不喜欢废话,上代码了:
头文件如下:
#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) <span style="white-space:pre"> </span>g_log.ScanfWrite(__FILE__, __FUNCTION__, __LINE__, x, p1)
#define SL_LOG2(x, p1, p2) <span style="white-space:pre"> </span>g_log.ScanfWrite(__FILE__, __FUNCTION__, __LINE__, x, p1, p2)
#define SL_LOG3(x, p1, p2, p3) <span style="white-space:pre"> </span>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_LOG2
SL_LOG31,2,3分别表示的是参数的个数,至于参数的类型和C语言格式化输出一样的。
日志输出结果包含:时间、文件名、函数名、日志内容。