vc 中寫log檔案
阿新 • • 發佈:2019-02-11
#pragma once #include <Windows.h> #include <stdio.h> static const char * KEYINFOPREFIX = " Key: \n"; static const char * ERRORPREFIX = " Error: \n"; static const char * WARNINGPREFIX = " Warning: \n"; static const char * INFOPREFIX = " Info: \n"; static const int MAX_STR_LEN = 1024; //日誌級別列舉 enum EnumLogLevel { LogLevelAll = 0, //所有資訊都寫日誌 LogLevelMid, //寫錯誤、警告資訊 LogLevelNormal, //只寫錯誤資訊 LogLevelStop //不寫日誌 }; class CLog { public: //預設建構函式 CLog(); //建構函式 CLog(const char * strLogPath, EnumLogLevel nLogLevel = LogLevelNormal); //解構函式 virtual ~CLog(); public: //寫關鍵資訊 void TraceKeyInfo(const char * strInfo, ...); //寫錯誤資訊 void TraceError(const char* strInfo, ...); //寫警告資訊 void TraceWarning(const char * strInfo, ...); //寫一般資訊 void TraceInfo(const char * strInfo, ...); //設定寫日誌級別 void SetLogLevel(EnumLogLevel nLevel); private: //寫檔案操作 void Trace(const char * strInfo); //獲取當前系統時間 char * GetCurrentTime(); //建立日誌檔名稱 void GenerateLogName(); //建立日誌路徑 void CreateLogPath(); private: //寫日誌檔案流 FILE * m_pFileStream; //寫日誌級別 EnumLogLevel m_nLogLevel; //日誌的路徑 char m_strLogPath[MAX_STR_LEN]; //日誌的名稱 char m_strCurLogName[MAX_STR_LEN]; //執行緒同步的臨界區變數 CRITICAL_SECTION m_cs; };
#include "StdAfx.h" #include "Log.h" #include <imagehlp.h> #include <time.h> #include <string.h> #include <stdarg.h> #pragma comment(lib, "DbgHelp.lib") //預設建構函式 CLog::CLog() { //初始化 memset(m_strLogPath, 0, MAX_STR_LEN); memset(m_strCurLogName, 0, MAX_STR_LEN); m_pFileStream = NULL; //設定預設的寫日誌級別 m_nLogLevel = LogLevelNormal; //初始化臨界區變數 InitializeCriticalSection(&m_cs); //建立日誌檔名 GenerateLogName(); Trace("***************log start********************"); } //建構函式 CLog::CLog(const char * strLogPath, EnumLogLevel nLogLevel):m_nLogLevel(nLogLevel) { //初始化 m_pFileStream = NULL; strcpy(m_strLogPath, strLogPath); InitializeCriticalSection(&m_cs); CreateLogPath(); GenerateLogName(); } //解構函式 CLog::~CLog() { Trace("***************log end********************"); //釋放臨界區 DeleteCriticalSection(&m_cs); //關閉檔案流 if(m_pFileStream) fclose(m_pFileStream); } //寫關鍵資訊介面 void CLog::TraceKeyInfo(const char * strInfo, ...) { if(!strInfo) return; char pTemp[MAX_STR_LEN] = {0}; strcpy(pTemp, GetCurrentTime()); strcat(pTemp, KEYINFOPREFIX); //獲取可變形參 va_list arg_ptr = NULL; va_start(arg_ptr, strInfo); vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr); va_end(arg_ptr); //寫日誌檔案 Trace(pTemp); arg_ptr = NULL; } //寫錯誤資訊 void CLog::TraceError(const char* strInfo, ...) { //判斷當前的寫日誌級別,若設定為不寫日誌則函式返回 if(m_nLogLevel >= LogLevelStop) return; if(!strInfo) return; char pTemp[MAX_STR_LEN] = {0}; strcpy(pTemp, GetCurrentTime()); strcat(pTemp, ERRORPREFIX); va_list arg_ptr = NULL; va_start(arg_ptr, strInfo); vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr); va_end(arg_ptr); Trace(pTemp); arg_ptr = NULL; } //寫警告資訊 void CLog::TraceWarning(const char * strInfo, ...) { //判斷當前的寫日誌級別,若設定為只寫錯誤資訊則函式返回 if(m_nLogLevel >= EnumLogLevel::LogLevelNormal) return; if(!strInfo) return; char pTemp[MAX_STR_LEN] = {0}; strcpy(pTemp, GetCurrentTime()); strcat(pTemp, WARNINGPREFIX); va_list arg_ptr = NULL; va_start(arg_ptr, strInfo); vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr); va_end(arg_ptr); Trace(pTemp); arg_ptr = NULL; } //寫一般資訊 void CLog::TraceInfo(const char * strInfo, ...) { //判斷當前的寫日誌級別,若設定只寫錯誤和警告資訊則函式返回 // if(m_nLogLevel >= EnumLogLevel::LogLevelMid) // return; if(!strInfo) return; char pTemp[MAX_STR_LEN] = {0}; strcpy(pTemp, GetCurrentTime()); strcat(pTemp,INFOPREFIX); va_list arg_ptr = NULL; va_start(arg_ptr, strInfo); vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr); va_end(arg_ptr); Trace(pTemp); arg_ptr = NULL; } //獲取系統當前時間 char * CLog::GetCurrentTime() { time_t curTime; struct tm * pTimeInfo = NULL; time(&curTime); pTimeInfo = localtime(&curTime); char temp[MAX_STR_LEN] = {0}; sprintf(temp, "%02d:%02d:%02d", pTimeInfo->tm_hour, pTimeInfo->tm_min, pTimeInfo->tm_sec); char * pTemp = temp; return pTemp; } //設定寫日誌級別 void CLog::SetLogLevel(EnumLogLevel nLevel) { m_nLogLevel = nLevel; } //寫檔案操作 void CLog::Trace(const char * strInfo) { if(!strInfo) return; try { //進入臨界區 EnterCriticalSection(&m_cs); //若檔案流沒有開啟,則重新開啟 if(!m_pFileStream) { char temp[1024] = {0}; strcat(temp, m_strLogPath); strcat(temp, m_strCurLogName); m_pFileStream = fopen(temp, "a+"); if(!m_pFileStream) { LeaveCriticalSection(&m_cs); return; } } //寫日誌資訊到檔案流 fprintf(m_pFileStream, "%s\n", strInfo); fflush(m_pFileStream); //離開臨界區 LeaveCriticalSection(&m_cs); } //若發生異常,則先離開臨界區,防止死鎖 catch(...) { LeaveCriticalSection(&m_cs); } } //建立日誌檔案的名稱 void CLog::GenerateLogName() { time_t curTime; struct tm * pTimeInfo = NULL; time(&curTime); pTimeInfo = localtime(&curTime); char temp[1024] = {0}; //日誌的名稱如:2013-01-01.log sprintf(temp, "%04d-%02d-%02d.log", pTimeInfo->tm_year+1900, pTimeInfo->tm_mon + 1, pTimeInfo->tm_mday); if(0 != strcmp(m_strCurLogName, temp)) { strcpy(m_strCurLogName,temp); if(m_pFileStream) fclose(m_pFileStream); char temp[1024] = {0}; strcat(temp, m_strLogPath); strcat(temp, m_strCurLogName); //以追加的方式開啟檔案流 m_pFileStream = fopen(temp, "a+"); } } //建立日誌檔案的路徑 void CLog::CreateLogPath() { if(0 != strlen(m_strLogPath)) { strcat(m_strLogPath, "\\"); } MakeSureDirectoryPathExists(m_strLogPath); }