最近写了一个日志类Clog,在实际系统中应用检验过了,效果不错,贴出来和大家交流交流,看还有没有需要改进的地方。
现对Clog类做部分说明:
这个类用到MFC的CFileFind,如果不用MFC,CFileFind实现的查找文件夹功能可用PathFileExists实现,当然,CString类型也需要转换。我已对写日志函数加锁,因此是线程安全的。
程序在当前目录下生成日志文件夹(如果该文件夹存在,则不生成),每天的日志放在一个以当天日期命名的文件夹中。
MAX_ROW 定义一个日志文件的最大行数,一个日志文件达到这个行数后即关闭,并创建一个新文件。
void Disable(); 关闭日志功能
void Enable(); 打开日志功能
int NewLogFile(); 创建新日志文件
BOOL IsChangeDay(); 判断是否跨天(凌晨0点)
CString GetCurntTime(); 获得当前时间字符串,格式为 2006-06-21-11-50
void WriteLogFile(const char* fmt, ... ); 写日志函数
头文件 LogFile.h
#include <sys/stat.h>
#include <fcntl.h>
#include <io.h>
#include <afxmt.h>
#define MAX_ROW 5000
class CLog
{
public:
void Disable();
void Enable();
CLog();
~CLog();
void WriteLogFile(const char* fmt, ... );
protected:
int NewLogFile();
BOOL IsChangeDay();
CString GetCurntTime();
private:
int m_filehandle;
int m_row;
int m_dirnum;
int m_filenum;
BOOL m_needlog;
char m_sContent[1024*1024];
CString m_strContent;
CString m_sCurtTime;
CString m_sYestady;
CString m_sToday;
CString m_sCurtDir;
CString m_sLogDir;
CString m_sLogDayDir;
CCriticalSection m_cs;
};
实现代码 LogFile.cpp
#include "stdafx.h"
#include "LogFile.h"
#include <direct.h>
static char log_directory[]="ivr_log";
CLog::CLog()
{
m_row = 0;
m_filehandle = 0;
m_dirnum = 0;
m_filenum = 0;
m_sCurtTime = _T("");
m_sToday = _T("");
m_sYestady = _T("");
m_sCurtDir = _T("");
m_sLogDir = _T("");
m_needlog = FALSE;
GetCurrentDirectory(_MAX_PATH,m_sCurtDir.GetBuffer(_MAX_PATH));
m_sCurtDir.ReleaseBuffer();
CString sDirName;
CFileFind f;
BOOL bHasLogDir = FALSE;
BOOL bFind = f.FindFile(m_sCurtDir + "\\*.*");
while (bFind)
{
bFind = f.FindNextFile();
if (f.IsDots()) continue;
if (f.IsDirectory())
{
sDirName = f.GetFileName();
sDirName.MakeLower();
if (sDirName == (CString)log_directory)
{
bHasLogDir = TRUE;
break;
}
}
}
m_sLogDir = m_sCurtDir + (CString)"\\" + (CString)log_directory;
if (!bHasLogDir)
{
_mkdir(m_sLogDir);
}
CString strTime = GetCurntTime ();
m_sToday = strTime.Mid(0,10);
}
CLog::~CLog()
{
_close(m_filehandle);
}
int CLog::NewLogFile()
{
CString strLogfileName;
if (m_filenum > 0)
{
_close(m_filehandle);
}
strLogfileName = m_sLogDayDir + (CString)"\\" + m_sCurtTime + (CString)".txt";
if((m_filehandle=_open(strLogfileName,_O_WRONLY| _O_CREAT|O_TRUNC, _S_IREAD | _S_IWRITE)) == -1)
{
printf("cannot create log file:%s\n",strLogfileName);
return -1;
}
m_filenum++;
return 0;
}
BOOL CLog::IsChangeDay()
{
m_sCurtTime = GetCurntTime();
m_sToday = m_sCurtTime.Mid(0,10);
if (m_sToday != m_sYestady)
{
m_sYestady = m_sToday;
m_sLogDayDir = m_sLogDir + (CString)"\\" + m_sToday;
_mkdir(m_sLogDayDir);
return TRUE;
}
return FALSE;
}
void CLog::WriteLogFile(const char* fmt, ... )
{
if (m_needlog)
{
m_cs.Lock();
if (m_row >= MAX_ROW || IsChangeDay())
{
if (NewLogFile() == -1)
{
m_cs.Unlock();
return;
}
m_row = 0;
}
va_list v_args;
va_start(v_args,fmt);
vsprintf( m_sContent, fmt, v_args );
va_end( v_args );
CString strTime;
CTime cTime = CTime::GetCurrentTime();
strTime = _T("20") + cTime.Format("%y-%m-%d %H:%M:%S");
/*
char sTime[32];
time_t now = time(NULL);
tm *tm_time = localtime(&now); //注意,localtime非线程安全
strftime(sTime,sizeof(sTime),"20%y-%m-%d %H:%M:%S",tm_time);
*/
m_strContent = (CString)"[" + strTime + (CString)"]" + (CString)m_sContent + "\n";
_write(m_filehandle,m_strContent,m_strContent.GetLength());
m_row++;
m_cs.Unlock();
}
}
CString CLog::GetCurntTime()
{
CString strTime;
CTime cTime = CTime::GetCurrentTime();
strTime = _T("20") + cTime.Format("%y-%m-%d-%H-%M-%S");
return strTime;
}
void CLog::Enable()
{
m_needlog = TRUE;
}
void CLog::Disable()
{
m_needlog = FALSE;
}