简单易用的C++日志组件

1、特点:

  • 简单易用,支持多参数。
  • 自动记录日志所在文件名称和代码行。
  • 自动备份和删除文件。默认最大日志文件3兆,最多存储5个日志文件。

 

2、用法:

仅仅有记录日志的函数,没有打开、关闭日志的啰嗦操作。只需要在记录日志时候,参照下述例记录日志即可:
LOGGER_WRITE(_T("我今天赚了:") << 12.358 << _T("元. 真好!");

输出格式示例:
2013/11/15 12:53:32 520 今天我赚了:12.358元.真好! [.\memwriter.cpp 128]

 

3、代码:

头文件代码如下:

#pragma once

#ifndef _STRSTREAM_
#include <sstream>
#endif
#ifndef _IOSTREAM_
#include <iostream> 
#endif
#ifndef _IOSFWD_
#include <iosfwd>
#endif
#ifndef __wtypes_h__
#include <wtypes.h>
#endif

#define WRITE_SIMPLE_LOGGER

namespace SIMPLE_LOGGER
{

#ifdef WRITE_SIMPLE_LOGGER

  #define LOGGER_WRITE(Value) { \
	sl_ostringstream logstream; logstream << Value; sl_string logstring = logstream.str(); \
	SIMPLE_LOGGER::S_Write(logstring.c_str(), __FILE__, __LINE__); }

  #define LOGGER_WRITE2(Value) { \
	sl_ostringstream logstream; logstream << Value; sl_string logstring = logstream.str(); \
	SIMPLE_LOGGER::S_Write(logstring.c_str(), __FILE__, __LINE__, TRUE); }

  #define LOGGER_WRITE_A(Value) { \
	sl_ostringstream_a logstream; logstream << Value; sl_string_a logstring = logstream.str(); \
	SIMPLE_LOGGER::S_WriteA(logstring.c_str(), __FILE__, __LINE__); }

  #define LOGGER_WRITE2_A(Value) { \
	sl_ostringstream_a logstream; logstream << Value; sl_string_a logstring = logstream.str(); \
	SIMPLE_LOGGER::S_WriteA(logstring.c_str(), __FILE__, __LINE__, TRUE); }
#else

  #define LOGGER_WRITE(Value)    NULL;
  #define LOGGER_WRITE2(Value)   NULL;
  #define LOGGER_WRITE_A(Value)  NULL;
  #define LOGGER_WRITE2_A(Value) NULL;
#endif

#ifdef UNICODE
  #define sl_ostringstream   std::wostringstream
  #define sl_string          std::wstring
  #define sl_ostringstream_a std::ostringstream
  #define sl_string_a        std::string
#else
  #define sl_ostringstream   std::ostringstream
  #define sl_string          std::string
  #define sl_ostringstream_a std::ostringstream
  #define sl_string_a        std::string
#endif

	void S_Write(const TCHAR *Value, const CHAR* File, int Line, BOOL bFlush = FALSE);
	void S_WriteA(const CHAR *Value, const CHAR* File, int Line, BOOL bFlush = FALSE);
};

 

实现文件如下: 

#ifndef _INC_STDIO
#include <STDIO.H>
#endif
#ifndef _INC_SHARE
#include <SHARE.H>
#endif
#ifndef __wtypes_h__
#include <WTYPES.H>
#endif
#ifndef _INC_WCHAR
#include <WCHAR.H>
#endif

#include "SimpleLogger.h"

#define SL_MAX_LOG_LENGTH           512
#define SL_MAX_FILE_SIZE            (1024 * 1024 * 3)
#define SL_MAX_FILE_COUNT           5

namespace SIMPLE_LOGGER {

	class CFileWriter
	{
	public:
		CFileWriter(void)
		{
#pragma warning(push)
#pragma warning(disable:4996)
			InitializeCriticalSection(&CritSection);
			FileSize = 0;
			hFileHandle = NULL;
			wmemset(FolderName, 0, MAX_PATH);
			wmemset(FullPathName, 0, MAX_PATH);
			wmemset(FileName, 0, MAX_PATH);
			WCHAR ModuleFile[MAX_PATH] = { 0 };
			::GetModuleFileNameW(GetModuleHandle(NULL), ModuleFile, MAX_PATH);
			WCHAR *Temp = wcsrchr(ModuleFile, L'.');
			wmemcpy(Temp, L"Log.txt", 7);
			//swprintf(Temp, (MAX_PATH - wcslen(ModuleFile) + wcslen(Temp)), L"%XLog.txt", GetCurrentProcessId());
			wmemcpy(FullPathName, ModuleFile, MAX_PATH);
			Temp = wcsrchr(ModuleFile, L'\\');
			wcscpy(FileName, Temp + 1); Temp[1] = 0;
			wcscpy(FolderName, ModuleFile);
			WCHAR BkFileName[MAX_PATH];
			BkFileCount = SL_MAX_FILE_COUNT;
			do {
				wprintf(BkFileName, L"%s%d_%s", FolderName, BkFileCount - 1, FileName);
			} while(!FileExisted(BkFileName) && --BkFileCount > 0);
			Open();
#pragma warning(pop)
		}

		~CFileWriter(void) 
		{
			Close();
			DeleteCriticalSection(&CritSection);
		}

		bool FileExisted(WCHAR *FileName) 
		{
			DWORD dwAttricutes = ::GetFileAttributesW(FileName);
			return dwAttricutes != DWORD(-1) && ((dwAttricutes & FILE_ATTRIBUTE_DIRECTORY) == 0) ;
		}

		void Open()
		{
			if (NULL != hFileHandle)
				return;

			hFileHandle = _wfsopen(FullPathName, L"ab", _SH_DENYNO);
			if (NULL == hFileHandle)
				return;

			fseek(hFileHandle, 0, SEEK_END);
			FileSize = ftell(hFileHandle);
		}

		void Close()
		{
			if (NULL != hFileHandle) {
				fclose(hFileHandle);
				hFileHandle = NULL;
				FileSize = 0;
			}			
		}

		void Write(const char *Value, const char* File, int Line, BOOL bFlush)
		{
			if (SL_MAX_FILE_SIZE < FileSize)
				FileBackup();

			if (NULL != hFileHandle) {
				SYSTEMTIME Time;
				GetLocalTime(&Time);
				FileSize += fprintf(hFileHandle,
					"%04d/%02d/%02d %02d:%02d:%02d %03d %s [%s %d]\r\n", 
					Time.wYear, Time.wMonth, Time.wDay, 
					Time.wHour, Time.wMinute, Time.wSecond, Time.wMilliseconds,
					Value, 
					File, Line);
				if (bFlush)
					fflush(hFileHandle);
			}
		}

		void FileBackup()
		{
			WCHAR BkFileName[MAX_PATH];
			if (SL_MAX_FILE_COUNT == BkFileCount) {
				WCHAR BkFileName2[MAX_PATH];
				wprintf(BkFileName2, L"%s%d_%s", FolderName, 0, FileName);
				DeleteFileW(BkFileName2);
				for (int i = 1; i < SL_MAX_FILE_COUNT; i++) {
					wprintf(BkFileName,  L"%s%d_%s", FolderName, i - 1, FileName);
					wprintf(BkFileName2, L"%s%d_%s", FolderName, i, FileName);
					_wrename(BkFileName2, BkFileName);
				}
				BkFileCount--;
			}

			Close();
			wprintf(BkFileName, L"%s%d_%s", FolderName, BkFileCount++, FileName);
			_wrename(FullPathName, BkFileName);
			Open();
		}

		LONG FileSize;
		UINT BkFileCount;
		FILE* hFileHandle;
		WCHAR FolderName[MAX_PATH];
		WCHAR FullPathName[MAX_PATH];
		WCHAR FileName[MAX_PATH];
		CRITICAL_SECTION CritSection;
	};

	void WriteToInternal(const CHAR *Value, const CHAR* File, int Line, BOOL bFlush)
	{
		try { 
			static CFileWriter LogWriter;
			CRITICAL_SECTION &hCritSection = LogWriter.CritSection;
			::EnterCriticalSection(&hCritSection);
			LogWriter.Write(Value, File, Line, bFlush); 
			::LeaveCriticalSection(&hCritSection);
		}
		catch (...) {}
	}

	__inline
	void Ellipsis(char Buff[3])
	{
		Buff[0] = '.'; Buff[1] = '.'; Buff[2] = '.';
	}

	void S_WriteA(const CHAR *Value, const CHAR* File, int Line, BOOL bFlush)
	{
		if (NULL != Value) {
			if (SL_MAX_LOG_LENGTH <= strlen(Value)) {
				char Buffer[SL_MAX_LOG_LENGTH] = { 0 };
				memcpy(Buffer, Value, SL_MAX_LOG_LENGTH - 4);
				Ellipsis(Buffer + (SL_MAX_LOG_LENGTH - 4));
				WriteToInternal(Buffer, File, Line, bFlush);
			}
			else
				WriteToInternal(Value, File, Line, bFlush);
		}
	}

	void S_Write(const TCHAR *Value, const CHAR* File, int Line, BOOL bFlush)
	{
		if (NULL != Value) {
#ifdef UNICODE
			char Buffer[SL_MAX_LOG_LENGTH] = { 0 };
			if (0 == WideCharToMultiByte(CP_ACP, 0, Value, -1, Buffer, SL_MAX_LOG_LENGTH - 1, NULL, NULL))
				Ellipsis(Buffer + (SL_MAX_LOG_LENGTH - 4));
			WriteToInternal(Buffer, File, Line, bFlush);
#else
			S_WriteA(Value, File, Line, bFlush);
#endif
		}
	}
};

 

 

你可能感兴趣的:(日志)