日志类可以作为一个练手项目,实现一个好的日志类并不容易,这里先出第一个版本,后期持续优化。功能简单对于新手非常友好,欢迎指正错误。
该日志类我命名为CClog,第一个C是class的意思,忽略这一点的话可以叫Clog。作用当然是日志记录,写日志操作是线程安全的,支持类似字符串Format的形式。
基于Windows平台
// test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include "Clog.h"
#include
int _tmain(int argc, _TCHAR* argv[])
{
//初始化工作,主要是创建目录、日志文件,必须只能在主线程完成-----线程不安全。
CClog::InitClog("dir\\");
//所有的写操作都是线程安全的
CClog::Instance().WriteLog("test");
CClog::Instance().WriteLogFormat("%d,%d,%d",110,112,1);
//资源释放,线程不安全
CClog::CloseClog();
return 0;
}
需要注意的是:
初始化工作,主要是创建目录、日志文件,必须只能在主线程完成-----线程不安全。
所有的写操作都是线程安全的
资源释放,线程不安全
CClog.h
#pragma once
//////////////////////////////////////////////////////////////////////////
// author: wzy
// csdn: https://blog.csdn.net/Think88666
// date: 2019-09-05
//////////////////////////////////////////////////////////////////////////
#include
class CClog
{
public:
static bool InitClog(const char *szDstDir);
static bool CloseClog();
const static CClog &Instance();
private:
static CClog *s_log;
private:
CClog(void);
FILE *m_hFile;
char *m_szFileName;
char *m_szFormatBuff;
HANDLE m_hMutex;
public:
~CClog(void);
void WriteLog(const char *szInfo) const;
void WriteLogFormat(const char *szFormat,...) const;
};
CClog.cpp
#include "StdAfx.h"
#include "Clog.h"
#include
#include
#include
#include
#include
#include
#include
#include
#define F_OK 0 /* Check for file existence */
#define X_OK 1 /* Check for execute permission. */
#define W_OK 2 /* Check for write permission */
#define R_OK 4 /* Check for read permission */
#define _MUTEX_START_ DWORD d = WaitForSingleObject(m_hMutex, INFINITE); \
if(d != WAIT_OBJECT_0 ) return;
#define _MUTEX_END_ ReleaseMutex(m_hMutex);
//初始化
CClog *CClog::s_log = NULL;
CClog::CClog(void):m_hFile(NULL),m_szFileName(NULL),m_szFormatBuff(NULL)
{
m_szFileName = new char[400];
m_szFormatBuff = new char [5120];
m_hMutex = CreateMutex(NULL,FALSE,NULL);
}
CClog::~CClog(void)
{
if(m_szFileName)
delete []m_szFileName;
if(m_hFile)
fclose(m_hFile);
if(m_szFormatBuff)
delete []m_szFormatBuff;
CloseHandle(m_hMutex);
}
bool CClog::InitClog( const char *szDstDir )
{
//check dir
int nDirFlag = access(szDstDir,F_OK | W_OK);
if(-1 == nDirFlag)
{
int nMkDirFlag = mkdir(szDstDir);
assert(-1 != nMkDirFlag);
if(-1 == nMkDirFlag)
return false;
}
//create file
srand((unsigned int)time(NULL));
int nRand = rand();
time_t nNowTime = time(0);
tm* nowTm = localtime(&nNowTime);
char szBuff[90] = "\0";
strftime(szBuff, sizeof(szBuff) - 1, "%Y_%m_%d__%H_%M_%S", nowTm);
char szBuff2[30] = "\0";
sprintf(szBuff2,"_%d.log",nRand%10000);
strcat(szBuff,szBuff2);
if(s_log) delete s_log;
s_log = new CClog;
int nLen = strlen(szDstDir);
assert(nLen+strlen(szBuff)<399);
strcpy(s_log->m_szFileName,szDstDir);
if(s_log->m_szFileName[nLen-1] != '/' && s_log->m_szFileName[nLen-1] != '\\' )
{
s_log->m_szFileName[nLen] = '/';
s_log->m_szFileName[nLen+1] = '\0';
}
strcat(s_log->m_szFileName,szBuff);
s_log->m_hFile = fopen(s_log->m_szFileName,"a");
assert(s_log);
if(!s_log->m_hFile)
return false;
fputs("###Powered by Clog###",s_log->m_hFile);
return true;
}
bool CClog::CloseClog()
{
if(s_log)
{
delete s_log;
s_log = NULL;
}
return true;
}
void CClog::WriteLog(const char *szInfo) const
{
_MUTEX_START_
assert(szInfo);
if(m_hFile)
{
time_t nNowTime = time(0);
tm* nowTm = localtime(&nNowTime);
char szBuff[90] = "\0";
strftime(szBuff, sizeof(szBuff) - 1, "\n%Y-%m-%d %H:%M:%S ", nowTm);
fputs(szBuff,m_hFile);
fputs(szInfo,m_hFile);
}
_MUTEX_END_
}
void CClog::WriteLogFormat(const char *szFormat,...) const
{
//线程安全
//申请占用互斥量
_MUTEX_START_
va_list aptr;
va_start(aptr, szFormat);
//保证不溢出
vsnprintf(m_szFormatBuff, 5119,szFormat, aptr);
va_end(aptr);
if(m_hFile)
{
time_t nNowTime = time(0);
tm* nowTm = localtime(&nNowTime);
char szBuff[90] = "\0";
strftime(szBuff, sizeof(szBuff) - 1, "\n%Y-%m-%d %H:%M:%S ", nowTm);
fputs(szBuff,m_hFile);
fputs(m_szFormatBuff,m_hFile);
}
_MUTEX_END_
}
const CClog &CClog::Instance()
{
assert(s_log);
return *s_log;
}
GIthub地址:
https://github.com/1002130915/CClog