VC 中使用Log 記錄文件

一、log.h 源碼

#pragma once

//===============================================================
// LOG::簡單的日誌工具
// 日誌功能包應該包括以下兩塊功能:
// 1. 每個日誌文本串
// 目前日誌文本串包括 [prefix][datetime][type][info...]
// a.多個進程輸出到同一個日誌文件,可通過prefix來區分每個進程; 可以忽略
// b.datetime可以用來測試時間
// c.類型可以設定[error|warn|debug],
// 由使用者任意使用,並不做明確標記; 也可以忽略
// d.info,可以根據實際情況任意格式化輸出,類似printf
// 2. 日誌文件
// a. 可將日誌串保存到文本,或者自己處理
// b. 支持併發寫操作
// c. 日誌文件的管理
//===============================================================

class LOG
{
public:
	LOG();
	virtual ~LOG();

public:
	//-日誌文件-
	//----如果沒有指定,則爲exe所在路徑下的log.log文件----
	static CString GetLogFile();
	static short SetLogFile(LPCTSTR strPath);
	static short ViewLogFile();

	//-前綴-
	//----如果多個進程往同一個文件輸出日誌,可以爲每個進程設置一個前綴----
	//----前綴出現在日期時間之前----
	static short SetPrefix(LPCTSTR strPrefix);

	//-日誌信息-
	//-獲取日誌字符串,可以另外-
	static CString sOutV(LPCTSTR strType, LPCTSTR strFormat = NULL, va_list valist = NULL);
	static CString sOut0(LPCTSTR strType, LPCTSTR strFormat = NULL,...);
	static CString sOut ( LPCTSTR strFormat = NULL,...);

	//-將日誌信息輸出到文件-
	static short OutV(LPCTSTR strType, LPCTSTR strFormat = NULL, va_list valist = NULL);
	static short Out0(LPCTSTR strType, LPCTSTR strFormat = NULL,...);
	static short Out (LPCTSTR strFormat = NULL,...);

protected:
	static CString s_strLogFile;
	static CString s_strLogPrefix;
	static HANDLE s_hWriteEvent;
};


二、log.cpp 源碼

#include "StdAfx.h"
#include "LOG.h"

// 得到可執行程序所在目錄
// BOOL bIncludeSep -- 是否包含最後的分隔符"\"
CString GetExePath(BOOL bIncludeSep)
{
	// 得到當前的文件名
	CString strFileName;
	GetModuleFileName(AfxGetInstanceHandle(), strFileName.GetBuffer(_MAX_PATH), _MAX_PATH);
	strFileName.ReleaseBuffer();
	// 得到當前目錄
	strFileName=strFileName.Left(strFileName.ReverseFind(_T('\\'))+1);

	if(bIncludeSep)
		return strFileName;
	else
		return strFileName.Left(strFileName.GetLength()-1);
}

//-獲取最後的文件名 如果給定文件不是全路徑,就是相對於exe-
CString GetFileForExePath(LPCTSTR strCurFileName)
{
	CString strPath = strCurFileName;
	if(!strPath.IsEmpty())
	{
		//-相對路徑-
		if(strPath.Find(_T(":"))<=0) 
		{ 
			strPath.Format(_T("%s%s"), GetExePath(FALSE), strCurFileName); 
		} 
	} 
	return strPath; 
} 

#define LOG_EVENT _T("ChyLogWrite") 
CString LOG::s_strLogFile = _T(""); 
CString LOG::s_strLogPrefix = _T(""); 
HANDLE LOG::s_hWriteEvent = NULL; 

LOG::LOG() 
{
} 

LOG::~LOG() 
{
} 

short LOG::SetLogFile(LPCTSTR strPath)
{
	if(strPath==NULL || strPath[0]==0)
		s_strLogFile = GetFileForExePath(_T("log.log"));
	else
		s_strLogFile = GetFileForExePath(strPath);

	return 1;
}

CString LOG::GetLogFile()
{
	return s_strLogFile;
}

short LOG::ViewLogFile()
{
	CString strLogFile = GetLogFile();
	ShellExecute(NULL, _T("open"), strLogFile, NULL, NULL, SW_SHOW);
	return strLogFile.IsEmpty()?0:1;
}

short LOG::SetPrefix(LPCTSTR strPrefix)
{
	if(strPrefix && strPrefix[0])
	{
		s_strLogPrefix = strPrefix;
	}

	return 1;
}

CString LOG::sOutV(LPCTSTR strType, LPCTSTR strFormat, va_list valist)
{ 
	CString strPart_Prefix;
	if(!s_strLogPrefix.IsEmpty())
	{
		strPart_Prefix.Format(_T("[%s]"), s_strLogPrefix);
	}

	CString strPart_Time;
	{
		SYSTEMTIME sysTime = {0};
		GetLocalTime(&sysTime);
		strPart_Time.Format(_T("[%2d-%2d %2d:%2d:%2d_%3d]"), 
			sysTime.wMonth, sysTime.wDay, 
			sysTime.wHour, sysTime.wMinute, sysTime.wSecond, 
			sysTime.wMilliseconds); 
	}

	CString strPart_Type;
	if(strType && strType[0])
	{
		strPart_Type.Format(_T("[%s]"), strType);
	}

	CString strPart_Info;
	{ 
		strPart_Info.FormatV(strFormat, valist);
	}

	CString str = strPart_Prefix + strPart_Time + strPart_Type+ strPart_Info;

	return str;
}

CString LOG::sOut0(LPCTSTR strType, LPCTSTR strFormat,...)
{
	va_list valist;
	va_start(valist, strFormat); 
	CString strInfo = sOutV(strType, strFormat, valist);
	va_end(valist); 

	return strInfo;
}

CString LOG::sOut(LPCTSTR strFormat,...)
{
	va_list valist;
	va_start(valist, strFormat);
	CString strInfo = sOutV(NULL, strFormat, valist);
	va_end(valist);

	return strInfo;
}


short LOG::OutV(LPCTSTR strType, LPCTSTR strFormat, va_list valist)
{
	//--
	if(s_hWriteEvent==NULL)
	{
		s_hWriteEvent = OpenEvent(0, FALSE,LOG_EVENT);
		if(s_hWriteEvent==NULL)
			s_hWriteEvent = CreateEvent(NULL, FALSE, TRUE, LOG_EVENT); 
	}

	WaitForSingleObject(s_hWriteEvent, INFINITE);

	//-打開關閉文件-
	if(s_strLogFile.IsEmpty())
		SetLogFile(NULL);
	CStdioFile file;
	if(file.Open(s_strLogFile, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite))
	{
		CString strPart_NewLine = _T("\n");
		CString strInfo = sOutV(strType, strFormat, valist); 
		CString str = strPart_NewLine + strInfo;

		file.SeekToEnd();
		file.WriteString(str);
		file.Close();
	}

	SetEvent(s_hWriteEvent);

	return 1;
}

short LOG::Out0(LPCTSTR strType, LPCTSTR strFormat,...)
{
	va_list valist;
	va_start(valist, strFormat); 
	short rtn = OutV(strType, strFormat, valist);
	va_end(valist);

	return rtn;
}

short LOG::Out(LPCTSTR strFormat,...)
{
	va_list valist;
	va_start(valist, strFormat);
	short rtn = OutV(NULL, strFormat, valist);
	va_end(valist);

	return rtn;
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章