CLog做了些许改进


// Main.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Common/Logger.h" 
#include <iostream>
#include "inifiles.h"

using namespace INIFILE;
using namespace LOGGER; 
CLogger g_log(LogLevel_Info, CLogger::GetAppPathA().append("log\\")); 



//获取源代码文件名,不用输入参数




DWORD WINAPI Fun(LPVOID lpParamter)
{
	while(1) 
	{ 
		g_log.Fatal("Fun thread display[%s:%d]", CLogger::ExtractFileName(__FILE__).c_str(), __LINE__) ;
		Sleep(5000);
	}
}

void TestIni(void)
{

	TIniFile *iniSet = new TIniFile("..\\Debug\\set.ini");
	iniSet->WriteFloat("CodeTool", "float", 13.56);
	std::cout << iniSet->ReadFloat("CodeTool", "float", 44.55) << std::endl;


	iniSet->WriteBool("CodeTool", "bool", true);
	std::cout << iniSet->ReadBool("CodeTool", "bool", false) << std::endl;

	iniSet->WriteInteger("CodeTool", "LogLevel", LOGGER::LogLevel_Warning);
	LOGGER::EnumLogLevel logLevel = (LOGGER::EnumLogLevel)iniSet->ReadInteger("CodeTool", "LogLevel", LOGGER::LogLevel_Info);
	std::cout << "log level:" << logLevel << std::endl;
	g_log.ChangeLogLevel(logLevel);

}



void main() 
{
	HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
	CloseHandle(hThread);

	TestIni();
	
	while (1)
	{
		g_log.Fatal("TraceFatal [%s:%d]", CLogger::ExtractFileName(__FILE__).c_str(), __LINE__); 
		g_log.Error("TraceError %s", "sun"); 
		string msg("string messages");
		g_log.Warn("TraceWarning %s", msg.c_str()); 
		g_log.Info("TraceInfo"); 

		g_log.Fatal("TraceFatal %d", 2); 
		g_log.Error("TraceError %f", 441.343567f); 
		g_log.Warn("TraceWarning"); 
		g_log.Info("TraceInfo"); 
		Sleep(1000);
	}




	std::cout << "已完成" << std::endl;
	getchar();
} 


//logger.h  

//类名:CLogger 
//功能介绍:Win平台日志记录功能,多线程安全,支持写日志级别的设置,日志格式包含日志等级,日志时间,文件名,行号信息 
//作者:sunflover 2016-1-15 14:31:27 
//修正者:andy 2016-9-11 17:07 

  
#ifndef _LOGGER_H_  
#define _LOGGER_H_  
#include <Windows.h>  
#include <stdio.h>  
#include <string>  
#include <fstream>



using std::string; 
using std::fstream;
  
namespace LOGGER  
{  
    //日志级别的提示信息  
    static const string strFatalPrefix = "FATAL <> - ";  
    static const string strErrorPrefix = "ERROR <> - ";  
    static const string strWarningPrefix = "WARN <> - ";  
    static const string strInfoPrefix = "INFO <> - ";  
  
    //日志级别枚举  
    typedef enum EnumLogLevel  
    {  
        LogLevel_Stop = 0,  //什么都不记录  
        LogLevel_Fatal =1,     //只记录严重错误  
        LogLevel_Error = 2,     //记录严重错误,普通错误  
        LogLevel_Warning = 3,   //记录严重错误,普通错误,警告  
        LogLevel_Info = 4,       //记录严重错误,普通错误,警告,提示信息(也就是全部记录)  
    };  
  
    class CLogger  
    {  
    public:  
        //nLogLevel:日志记录的等级,可空  
        //strLogPath:日志目录,可空  
        //strLogName:日志名称,可空  
        CLogger(EnumLogLevel nLogLevel = LogLevel_Info, const string strLogPath = "", const string strLogName = "");  
        //析构函数  
        virtual ~CLogger();  

    public:  
        //写严重错误信息  
        void Fatal(const char *lpcszFormat, ...);  
        //写错误信息  
        void Error(const char *lpcszFormat, ...);  
        //写警告信息  
        void Warn(const char *lpcszFormat, ...);  
        //写提示信息  
        void Info(const char *lpcszFormat, ...);  
        //改变写日志级别  
        void ChangeLogLevel(EnumLogLevel nLevel);  
        //获取程序运行路径  
        static string GetAppPathA();  
        //格式化字符串  
        static string FormatString(const char *lpcszFormat, ...); 
		static string IntToStr(int val);
		//返回完整文件名中的文件名称 (带扩展名),如"mytest.doc"
		static string ExtractFileName(const char *szFilePath); 

    private:  
        //写文件操作  
        void Trace(const string &strLog);  
        //获取当前系统时间  
        std::string GetTime();  


    private:  
        //写日志文件流  
		fstream m_fout; 
        //写日志级别  
        EnumLogLevel m_nLogLevel;  
        //日志目录  
        string m_strLogPath;  
        //日志的名称  
        string m_strLogName;  
        //日志文件全路径  
        string m_strLogFilePath;  
        //线程同步的临界区变量  
        CRITICAL_SECTION m_cs;  
    };  
}  
  
#endif  

//logger.cpp  
#include "stdafx.h"
#include "logger.h"
#include "logger.h"  
#include <time.h>  
#include <stdarg.h>  
#include <direct.h>  
#include <vector>
#include <sstream>
#include <Dbghelp.h>  

#pragma comment(lib,"Dbghelp.lib") 

 
using std::vector;

namespace LOGGER  
{  
	CLogger::CLogger(EnumLogLevel nLogLevel, const string strLogPath, const string strLogName)  
		:m_nLogLevel(nLogLevel),  
		m_strLogPath(strLogPath),  
		m_strLogName(strLogName)  
	{  
 
		if (m_strLogPath.empty())  
		{  
			m_strLogPath = GetAppPathA();  
		}  
		if (m_strLogPath[m_strLogPath.length()-1] != '\\')  
		{  
			m_strLogPath.append("\\");  
		}  
		//创建文件夹  
		MakeSureDirectoryPathExists(m_strLogPath.c_str());  
		//创建日志文件  
		if (m_strLogName.empty())  
		{  
			time_t curTime;  
			time(&curTime);  
			tm tm1;  
			localtime_s(&tm1, &curTime);  
			m_strLogName = FormatString("%04d%02d%02d.log", tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday);   //日志的名称如:20160910.log
		}  
		m_strLogFilePath = m_strLogPath.append(m_strLogName);  

		//以追加的方式打开文件流  
		m_fout.open(m_strLogFilePath.c_str(), fstream::app, _SH_DENYNO);

		InitializeCriticalSection(&m_cs);  
	}  

	//-------------------------------------------------------------------------------------------------------------------------

	//析构函数  
	CLogger::~CLogger()  
	{  
		//释放临界区  
		DeleteCriticalSection(&m_cs);  
		//关闭文件流  
		if (m_fout)  
		{  
			m_fout.close();  
		}  
	}  


	//-------------------------------------------------------------------------------------------------------------------------

	//写严重错误信息  
	void CLogger::Fatal(const char *lpcszFormat, ...)  
	{  
		//判断当前的写日志级别  
		if (LogLevel_Fatal > m_nLogLevel)  
			return;  
		string strResult;  
		if (NULL != lpcszFormat)  
		{  
			va_list marker = NULL;  
			va_start(marker, lpcszFormat); //初始化变量参数  
			size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度  
			std::vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组  
			int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);  
			if (nWritten > 0)  
			{  
				strResult = &vBuffer[0];  
			}  
			va_end(marker); //重置变量参数  
		}  
		if (strResult.empty())  
		{  
			return;  
		}  
		string strLog = GetTime();  //IntToStr(GetCurrentThreadId()) + " " + 
		strLog.append(strFatalPrefix).append(strResult);  

		//写日志文件  
		Trace(strLog);  
	}  

	//-------------------------------------------------------------------------------------------------------------------------

	//写错误信息  
	void CLogger::Error(const char *lpcszFormat, ...)  
	{  
		//判断当前的写日志级别  
		if (LogLevel_Error > m_nLogLevel)  
			return;  
		string strResult;  
		if (NULL != lpcszFormat)  
		{  
			va_list marker = NULL;  
			va_start(marker, lpcszFormat); //初始化变量参数  
			size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度  
			vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组  
			int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);  
			if (nWritten > 0)  
			{  
				strResult = &vBuffer[0];  
			}  
			va_end(marker); //重置变量参数  
		}  
		if (strResult.empty())  
		{  
			return;  
		}  
		string strLog = GetTime();  
		strLog.append(strErrorPrefix).append(strResult);  

		//写日志文件  
		Trace(strLog);  
	}  

	//-------------------------------------------------------------------------------------------------------------------------

	//写警告信息  
	void CLogger::Warn(const char *lpcszFormat, ...)  
	{  
		//判断当前的写日志级别  
		if (LogLevel_Warning > m_nLogLevel)  
			return;  
		string strResult;  
		if (NULL != lpcszFormat)  
		{  
			va_list marker = NULL;  
			va_start(marker, lpcszFormat); //初始化变量参数  
			size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度  
			vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组  
			int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);  
			if (nWritten > 0)  
			{  
				strResult = &vBuffer[0];  
			}  
			va_end(marker); //重置变量参数  
		}  
		if (strResult.empty())  
		{  
			return;  
		}  
		string strLog = GetTime();  
		strLog.append(strWarningPrefix).append(strResult);  

		//写日志文件  
		Trace(strLog);  
	}  

	//-------------------------------------------------------------------------------------------------------------------------

	//写一般信息  
	void CLogger::Info(const char *lpcszFormat, ...)  
	{  
		//判断当前的写日志级别  
		if (LogLevel_Info > m_nLogLevel)  
			return;  
		string strResult;  
		if (NULL != lpcszFormat)  
		{  
			va_list marker = NULL;  
			va_start(marker, lpcszFormat); //初始化变量参数  
			size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度  
			vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组  
			int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);  
			if (nWritten > 0)  
			{  
				strResult = &vBuffer[0];  
			}  
			va_end(marker); //重置变量参数  
		}  
		if (strResult.empty())  
		{  
			return;  
		}  
		string strLog = GetTime();  
		strLog.append(strInfoPrefix).append(strResult);  

		//写日志文件  
		Trace(strLog);  
	}  

	//-------------------------------------------------------------------------------------------------------------------------

	//获取系统当前时间  
	string CLogger::GetTime()  
	{  
		time_t curTime;  
		time(&curTime);  
		tm tm1;  
		localtime_s(&tm1, &curTime);  
		//2016-01-01 21:30:00  
		string strTime = FormatString("%02d-%02d-%02d %02d:%02d:%02d ", (tm1.tm_year + 1900)%100, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec);  

		return strTime;  
	}  

	//-------------------------------------------------------------------------------------------------------------------------

	//改变写日志级别  
	void CLogger::ChangeLogLevel(EnumLogLevel nLevel)  
	{  
		m_nLogLevel = nLevel;  
	}  

	//-------------------------------------------------------------------------------------------------------------------------

	//写文件操作  
	void CLogger::Trace(const string &strLog)  
	{  
		try  
		{  
			//进入临界区  
			EnterCriticalSection(&m_cs);  
			//若文件流没有打开,则重新打开  
			if (!m_fout.is_open())  
			{  
				m_fout.open(m_strLogFilePath.c_str(), fstream::app, _SH_DENYNO);  
				if (!m_fout)  
				{  
					return;  
				}  
			}  
			//写日志信息到文件流  
			m_fout << strLog.c_str() << std::endl;  
			//离开临界区  
			LeaveCriticalSection(&m_cs);  
		}  
		//若发生异常,则先离开临界区,防止死锁  
		catch (...)  
		{  
			LeaveCriticalSection(&m_cs);  
		}  
	}  

	//-------------------------------------------------------------------------------------------------------------------------

	string CLogger::GetAppPathA()  
	{  
		char szFilePath[MAX_PATH] = { 0 }, szDrive[MAX_PATH] = { 0 }, szDir[MAX_PATH] = { 0 }, szFileName[MAX_PATH] = { 0 }, szExt[MAX_PATH] = { 0 };  
		GetModuleFileNameA(NULL, szFilePath, sizeof(szFilePath));  
		_splitpath_s(szFilePath, szDrive, szDir, szFileName, szExt);  

		string str(szDrive);  
		str.append(szDir);  
		return str;  
	}  

	//-------------------------------------------------------------------------------------------------------------------------

	string CLogger::FormatString(const char *lpcszFormat, ...)  
	{  
		string strResult;  
		if (NULL != lpcszFormat)  
		{  
			va_list marker = NULL;  
			va_start(marker, lpcszFormat); //初始化变量参数  
			size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度  
			vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组  
			int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);  
			if (nWritten > 0)  
			{  
				strResult = &vBuffer[0];  
			}  
			va_end(marker); //重置变量参数  
		}  
		return strResult;  
	} 

	//-------------------------------------------------------------------------------------------------------------------------
	string CLogger::IntToStr(int val)
	{
		string tmp;
		std::stringstream ss;
		ss << val;
		ss >> tmp;
		return tmp;
	}


	//-------------------------------------------------------------------------------------------------------------------------
	//返回完整文件名中的文件名称 (带扩展名),如"mytest.doc"
	string CLogger::ExtractFileName(const char *szFilePath)
	{
		char szDrive[MAX_PATH] = { 0 }, szDir[MAX_PATH] = { 0 }, szFileName[MAX_PATH] = { 0 }, szExt[MAX_PATH] = { 0 }; 
		_splitpath_s(szFilePath, szDrive, szDir, szFileName, szExt);
		string fileName = string(szFileName) + szExt;
		return fileName;
	}
	
}//end of namespace  LOGGER

#pragma once

#include <atlstr.h>


namespace INIFILE
{
	class TIniFile
	{
	public:
		TIniFile(const CString FileName);
		virtual ~TIniFile();

	public:
		virtual CString ReadString(const CString Section, const CString Ident, const CString Default);
		virtual void WriteString(const CString Section, const CString Ident, const CString Value);
		virtual int ReadInteger(const CString Section, const CString Ident, int Default);
		virtual void WriteInteger(const CString Section, const CString Ident, int Value);
		virtual double ReadFloat(const CString Section, const CString Ident, double Default);		
		virtual void WriteFloat(const CString Section, const CString Ident, double Value);
		virtual bool ReadBool(const CString Section, const CString Ident, bool Default);
		virtual void WriteBool(const CString Section, const CString Ident, bool Value);

	private:
		CString m_FileName;
	};
}//end IniFile

#include "stdafx.h"
#include "inifiles.h"
#include <stdlib.h>
#include <sstream>




namespace INIFILE
{
	#define  MAX_TXTLEN		256	//最大行数

	TIniFile::TIniFile(const CString FileName)
	{
		m_FileName = FileName;
	}

	TIniFile::~TIniFile()
	{

	}

	//-------------------------------------------------------------------------------------------------------

	CString TIniFile::ReadString(const CString Section, const CString Ident, const CString Default)
	{
		CString strValue;
		::GetPrivateProfileString(Section, Ident, Default, strValue.GetBuffer(MAX_TXTLEN), MAX_TXTLEN, m_FileName);
		strValue.ReleaseBuffer();
		return strValue;
	}
	//-------------------------------------------------------------------------------------------------------

	void TIniFile::WriteString(const CString Section, const CString Ident, const CString Value)
	{
		::WritePrivateProfileString(Section, Ident, Value, m_FileName);
	}

	//-------------------------------------------------------------------------------------------------------

	int TIniFile::ReadInteger(const CString Section, const CString Ident, int Default)
	{
		return ::GetPrivateProfileInt(Section, Ident, Default, m_FileName);
	}
	//-------------------------------------------------------------------------------------------------------

	void TIniFile::WriteInteger(const CString Section, const CString Ident, int Value)
	{
		CString strValue;
		strValue.Format("%d", Value);
		::WritePrivateProfileString(Section, Ident, strValue, m_FileName);
	}

	//-------------------------------------------------------------------------------------------------------

	double TIniFile::ReadFloat(const CString Section, const CString Ident, double Default)
	{
		CString strDefault;
		strDefault.Format("%lf", Default);

		CString strValue;
		::GetPrivateProfileString(Section, Ident, strDefault, strValue.GetBuffer(MAX_TXTLEN), MAX_TXTLEN, m_FileName);
		strValue.ReleaseBuffer();

		std::stringstream stream;
		double val;
		stream << strValue;
		stream >> val;
		return val;
	}

	//-------------------------------------------------------------------------------------------------------

	void TIniFile::WriteFloat(const CString Section, const CString Ident, double Value)
	{
		CString strValue;
		strValue.Format("%lf", Value);
		::WritePrivateProfileString(Section, Ident, strValue, m_FileName);
	}

	//-------------------------------------------------------------------------------------------------------
	bool TIniFile::ReadBool(const CString Section, const CString Ident, bool Default)
	{
		CString strDefault, strValue;
		strDefault.Format("%d", Default);
		::GetPrivateProfileString(Section, Ident, strDefault, strValue.GetBuffer(MAX_TXTLEN), MAX_TXTLEN, m_FileName);
		strValue.ReleaseBuffer();

		std::stringstream stream;
		bool val;
		stream << strValue;
		stream >> val;
		return val;
	}

	void TIniFile::WriteBool(const CString Section, const CString Ident, bool Value)
	{
		CString strValue;
		strValue.Format("%d", Value);
		::WritePrivateProfileString(Section, Ident, strValue, m_FileName);
	}

}// end namespace IniFile



程序是基于VS2008的,由于一些低版本的编译器不支持,大家自行改下

m_fout.open(m_strLogFilePath.c_str(), fstream::app, _SH_DENYNO); 改成m_fout.open(m_strLogFilePath.c_str(), fstream::app);

size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度     _vscprintf这个其它编译器没有的。建议直接采用 size_t  nLength  = 1024;

_vsnprintf_s换成stdlib标准里的 vsnprintf


另外,如果VS2013烦人的警告 让你把sprintf换成sprintf_s等

在cpp开头加#param warning(disable:4996)


对CLog做了一些改进

andy 2016-9-11 shenzhen

原文来自:http://blog.csdn.net/sunflover454/article/details/49758801

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值