Windowsログクラス(c++)

7836 ワード

開発製品ではログ記録を使用しますが、ログファイルのサイズに制限があります.このような機能に対して、本人はログファイル操作クラスを書いて、機能を実現しました.
1.ログを書き込み可能ディレクトリに記録し、異なるパラメータで異なるディレクトリに保存できる
2.ログは現在512 K制限されているが、このサイズを超えると、元の半分を切り取り、古い半分のログを破棄する.この制限はそのマクロを修正すればよい.
3.運行ログごとに特別な記号で分けて、簡単に見ることができる
4.ログのアップロードを考慮すると、完全な実行記録が1回必要なので、切り取り時に判断し、少なくとも1回は完全なログを保存するので、そのプロセスであれば
ずっと退出しないのはあまり適用されません(自分で変更する必要があります)、アップロード時に完全な記録を残すため、一度未満のログを切り取ることはできません.以下は実装コードです.
5.マルチスレッド同時呼び出しのサポート
cpp実装
#include "stdafx.h"
#include "ComLogToFile.h"

#define LOG_MAXLEN	2048
#define PROCESS_LOG_BEG "**********************************InitLogFile**********************************
" #define PROCESS_LOG_END "**********************************EndLogFile***********************************

" // 512K #define MAX_LOG_FILESIZE 512 * 1024 static HANDLE g_hDALogEvent = NULL; static TCHAR g_szLogFilePath[MAX_PATH] = {0}; static BOOL g_bLogInit = FALSE; CDALogFile::CDALogFile() { } CDALogFile::~CDALogFile() { } void CDALogFile::vFileFlat(const char *pContent, int nLen) { if(NULL == pContent || nLen < 0) return ; int nHalf = nLen >> 1;// int nMoveLen = strlen(PROCESS_LOG_BEG); const char *pSearch = pContent; while(pSearch != NULL) { pSearch = strstr(pSearch, PROCESS_LOG_BEG); if(pSearch != NULL) { int OffsetSize = (int)(pSearch - pContent); if(OffsetSize >= nHalf) { // BEG, FILE *filelog = NULL; //w+ , if(_tfopen_s(&filelog, g_szLogFilePath, _T("w+")) == 0) { // fwrite(pSearch, sizeof(char), nLen - OffsetSize, filelog); fflush(filelog); fclose(filelog); } break; } //Search pSearch += nMoveLen; } } } void CDALogFile::vCheckFileSize() { if(WaitForSingleObject(g_hDALogEvent, 2000) == WAIT_TIMEOUT) { return; } FILE *filelog = NULL; // , if(_tfopen_s(&filelog, g_szLogFilePath, _T("r")) == 0) { if(fseek(filelog, 0, SEEK_END) == 0) { // long nfsize = ftell(filelog); if(nfsize >= MAX_LOG_FILESIZE) { // , char *pStr = new char[nfsize]; if(pStr) { fseek(filelog, 0, SEEK_SET); int nReaded = fread(pStr, sizeof(char), nfsize, filelog); // nReaded bufSize // ZeroMemory pStr, ZeroMemory if(nReaded < nfsize) { pStr[nReaded] = '\0'; } //close , =NULL fclose(filelog); filelog = NULL; // ( ) vFileFlat(pStr, nReaded); //free buffer delete [] pStr; } } } } // close if(filelog) { fclose(filelog); } SetEvent(g_hDALogEvent); } string CDALogFile::ts2ms(LPCTSTR szSrc, int cchWideChar /* = -1 */) { string strDst; if ( NULL == szSrc || 0 == cchWideChar ){ return strDst; } #ifdef _UNICODE char* pBuff = NULL; int nLen = WideCharToMultiByte(CP_ACP, 0, szSrc, cchWideChar, NULL, 0, NULL, NULL); if ( nLen > 0 ){ pBuff = new char[nLen + 1]; if ( pBuff ){ WideCharToMultiByte(CP_ACP, 0, szSrc, cchWideChar, pBuff, nLen, NULL, NULL); pBuff[nLen] = 0; strDst.assign(pBuff); delete[] pBuff; } } #else strDst.assign(szSrc); #endif return strDst; } void CDALogFile::vFormatTime(TCHAR *szOut, int nLen) { SYSTEMTIME stime; GetLocalTime(&stime); _stprintf_s(szOut, nLen, _T("%02d-%02d %02d:%02d:%02d.%03d:"), stime.wMonth, stime.wDay, stime.wHour, stime.wMinute, stime.wSecond, stime.wMilliseconds); } void CDALogFile::vWriteFile(const char *szStr, int len /* = -1 */) { if(WaitForSingleObject(g_hDALogEvent, 2000) == WAIT_TIMEOUT) { OutputDebugString(_T("!!!!!WriteLogTimeOut!!!!!")); return; } if(len == -1) { len = strlen(szStr); } FILE *filelog = NULL; if(_tfopen_s(&filelog, g_szLogFilePath, _T("a")) == 0) { fwrite(szStr, sizeof(char), len, filelog); fflush(filelog); fclose(filelog); } SetEvent(g_hDALogEvent); } void CDALogFile::InitLogFile(const TCHAR *sAppKey) { if(!g_bLogInit) { g_hDALogEvent = CreateEvent(NULL, FALSE, TRUE, NULL); TCHAR szPath[MAX_PATH]; if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath))) { _tcscat_s(szPath, MAX_PATH, _T("\\TestLog")); if(_taccess(szPath, 0x00) != 0) { CreateDirectory(szPath, NULL); } if(_tcslen(sAppKey) < 100) { _stprintf_s(g_szLogFilePath, MAX_PATH, _T("%s\\%s\\"), szPath, sAppKey); }else { TCHAR szCopy[MAX_PATH] = {0}; _tcsnccpy_s(szCopy, MAX_PATH, sAppKey, 100); _stprintf_s(g_szLogFilePath, MAX_PATH, _T("%s\\%s\\"), szPath, szCopy); } if(_taccess(g_szLogFilePath, 0x00) != 0) { CreateDirectory(g_szLogFilePath, NULL); } TCHAR LogFile[MAX_PATH] = {0}; _stprintf_s(LogFile, MAX_PATH, _T("dalog_%s.log"), sAppKey); //SYSTEMTIME stime; //GetLocalTime(&stime); //_stprintf_s(LogFile, MAX_PATH, _T("%04d-%02d-%02d.log"), stime.wYear, stime.wMonth, stime.wDay); _tcscat_s(g_szLogFilePath, MAX_PATH, LogFile); } g_bLogInit = TRUE; // vCheckFileSize(); vWriteFile(PROCESS_LOG_BEG); } } void CDALogFile::GetLogFile(TCHAR *szPath, int nLen) { if(szPath && nLen > 0) { _tcscpy_s(szPath, nLen, g_szLogFilePath); } } // void CDALogFile::Log(const TCHAR* ptzFormat, ...) { if(!g_bLogInit) { return ; } #pragma warning(disable:4996) if(!ptzFormat) return; va_list vlArgs; TCHAR tzText[LOG_MAXLEN]; TCHAR tzText2[LOG_MAXLEN + 256]; TCHAR szTimesFormat[100]; vFormatTime(szTimesFormat, 100); va_start(vlArgs, ptzFormat); if(_vsctprintf(ptzFormat,vlArgs) < LOG_MAXLEN) { #ifdef _UNICODE vswprintf_s(tzText, LOG_MAXLEN, ptzFormat, vlArgs); #else _vstprintf_s(tzText, LOG_MAXLEN, ptzFormat, vlArgs); #endif }else { _tcscpy_s(tzText, LOG_MAXLEN, _T("Input va_list too long, won't show the values!!!!!!!!")); } _stprintf_s(tzText2, LOG_MAXLEN + 256, _T("%s[%d-%d]\t%s
"), szTimesFormat, GetCurrentProcessId(), GetCurrentThreadId(), tzText); #ifdef _TRACK OutputDebugString(tzText2); #endif string logs = ts2ms(tzText2); vWriteFile(logs.c_str(), logs.length()); va_end(vlArgs); #pragma warning(default:4996) } void CDALogFile::Release() { if(g_bLogInit) { vWriteFile(PROCESS_LOG_END); CloseHandle(g_hDALogEvent); g_bLogInit = FALSE; } }

テストコード:
int nOverNum = 0;
DWORD WINAPI LogThreadProc(
						LPVOID lpParameter
						)
{

	srand((unsigned)time(NULL));
	int times = rand() % 200;
	
	int i = 0;
	printf("Thread id %d times %d
", GetCurrentThreadId(), times); while( i++ < times) { CDALogFile::Log(_T("Thread in times %d, i = %d"), times, i); if(i > 20) { CDALogFile::Log(_T("Thread in i is bigger, ,we should check this sen!!!"), times, i); } int sleepT = rand() % 20; Sleep(sleepT * 100); } nOverNum ++; printf("Thread id %d out, number ; %d!
", GetCurrentThreadId(), nOverNum); return 0; } void TestLogsFile() { OutputDebugString(_T("Before InitLogFile")); CDALogFile::InitLogFile(_T("MyLogs")); OutputDebugString(_T("After InitLogFile")); CDALogFile::Log(_T("Test1")); OutputDebugString(_T("Test1")); CDALogFile::Log(_T("Test2")); OutputDebugString(_T("Test2")); CDALogFile::Log(_T("Test3")); OutputDebugString(_T("Test3")); for (int i = 0; i < 10; i++) { CreateThread(NULL, 0, LogThreadProc, NULL, 0, NULL); Sleep(500); } getchar(); CDALogFile::Release(); }

上のテストコードで何度も走ったが、まだ問題が発見されていないので、コード規範やバグ上の間違いを指摘してください.