Created
March 27, 2011 16:20
-
-
Save thinkhy/889338 to your computer and use it in GitHub Desktop.
A Log implement in Win32 C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
#include "Cx_SeaLog.h" | |
#include <string> | |
#include <sstream> | |
#include <vector> | |
using namespace std; | |
#define MAX_LOGFILE_SIZE 1024*1024 // LOG文件最大为1MB | |
CRITICAL_SECTION Cx_SeaLog::s_csLog; //< 日志关键区 | |
///////////////////////////////////////////////////////////////////////////// | |
#define Int64ShllMod32(a, b) ((DWORDLONG)(a) << (b)) | |
// reverse of part of transformation in InternetTimeFromTime_t | |
// A filetime is the numbers of 100 ns since Jan 1, 1601, while | |
//a dostime is the number of seconds since Jan 1, 1970. | |
static void FileTimeToDosTime( FILETIME ft, DWORD* pTime_t) | |
{ | |
//dwl1970Offset is the number of ns from 1601 to 1970 | |
const DWORDLONG dwl1970Offset = 0x019dae9064bafa80; | |
DWORDLONG lVal; | |
lVal = ft.dwLowDateTime; | |
lVal |= Int64ShllMod32( Int64ShllMod32( ft.dwHighDateTime, 16), 16 ); | |
*pTime_t = (DWORD)((lVal - dwl1970Offset) / 10000000); | |
return; | |
} | |
///////////////////////////////////////////////////////////////////////////// | |
void Cx_SeaLog::Init() | |
{ | |
InitializeCriticalSection(&s_csLog); | |
} | |
void Cx_SeaLog::UnInit() | |
{ | |
DeleteCriticalSection(&s_csLog); | |
} | |
Cx_SeaLog::Cx_SeaLog() | |
{ | |
} | |
Cx_SeaLog::~Cx_SeaLog() | |
{ | |
} | |
void Cx_SeaLog::GetCurTime(wstring& strCurTime, | |
const wstring& strFormat /* = L"\r\n%d-%02d-%02d %02d:%02d:%02d \t"*/) const | |
{ | |
// Write current time | |
SYSTEMTIME systime ={0}; | |
GetLocalTime(&systime); | |
TCHAR szTime[256] = {0}; | |
wsprintf(szTime, strFormat.c_str(), systime.wYear, systime.wMonth, | |
systime.wDay, systime.wHour, systime.wMinute, systime.wSecond); | |
strCurTime = wstring(szTime); | |
return; | |
} | |
bool Cx_SeaLog::BackupLogFile(const std::wstring & strLogFile) | |
{ | |
// 以当前时间为备份文件名 | |
wstring strCurTime; | |
GetCurTime(strCurTime); | |
wstring strNewFile = strCurTime + L".txt"; | |
WCHAR szNewFile[MAX_PATH] = L"\0"; | |
::GetModuleFileName(NULL, szNewFile, MAX_PATH); | |
::PathRemoveFileSpec(szNewFile); | |
::PathAppend(szNewFile, L"Log"); | |
::PathAppend(szNewFile, strNewFile.c_str()); | |
return TRUE == ::MoveFile(strLogFile.c_str(), szNewFile); | |
} | |
// TODO: !! 代码需要整理 [Huangye 11/03/26] | |
void Cx_SeaLog::WriteLog(const std::wstring& strLog) | |
{ | |
EnterCriticalSection(&s_csLog); | |
static TCHAR szFileName[MAX_PATH] = L""; | |
if (wcscmp(szFileName, L"") == 0) | |
{ | |
::GetModuleFileName(NULL, szFileName, MAX_PATH); | |
::PathRemoveFileSpec(szFileName); | |
::PathAppend(szFileName, L"Log"); | |
::PathAppend(szFileName, L"Log.txt"); | |
} | |
HANDLE hFile = ::CreateFile(szFileName, GENERIC_WRITE, 0, | |
NULL, OPEN_ALWAYS, 0, NULL ); | |
if (hFile == INVALID_HANDLE_VALUE) | |
return; | |
DWORD nWrite = 0; | |
int nSize = 0; | |
if (hFile) | |
{ | |
nSize = ::GetFileSize(hFile, NULL ); | |
} | |
// 日志文件大小超过1MB | |
if (nSize >= MAX_LOGFILE_SIZE) | |
{ | |
CloseHandle(hFile); | |
// 备份当前日志文件 | |
VERIFY(BackupLogFile(szFileName)); | |
// 重新打开文件句柄 | |
HANDLE hFile = ::CreateFile(szFileName, GENERIC_WRITE, 0, | |
NULL, OPEN_ALWAYS, 0, NULL ); | |
ASSERT(hFile != INVALID_HANDLE_VALUE); | |
if (hFile == INVALID_HANDLE_VALUE) | |
return; | |
ASSERT(0 == ::GetFileSize(hFile, NULL )); | |
nSize = 0; // 文件大小为零 | |
} | |
// 首先写入UTF-16的文件头 | |
if (nSize == 0) | |
{ | |
const unsigned char LeadBytes[] = {0xFF, 0xFE}; | |
::WriteFile( hFile, LeadBytes, 2, &nWrite, NULL ); | |
::FlushFileBuffers(hFile); | |
} | |
// 寻道到文件最后的位置 | |
LONG dwMoveH = 0; | |
DWORD dwMoveL = 0; | |
dwMoveL = ::SetFilePointer(hFile, dwMoveL, &dwMoveH, FILE_END); | |
// 记录当前时间 | |
wstring strCurTime; | |
GetCurTime(strCurTime); | |
DWORD dwNumberOfBytesToWrite = strCurTime.size(); | |
::WriteFile( hFile, strCurTime.c_str(), | |
dwNumberOfBytesToWrite * sizeof(WCHAR), &nWrite, NULL ); | |
ASSERT(dwNumberOfBytesToWrite * sizeof(WCHAR) == nWrite); | |
// 写日志 | |
::WriteFile( hFile, strLog.c_str(), strLog.size() * sizeof(WCHAR), &nWrite, NULL ); | |
ASSERT(strLog.size() * sizeof(WCHAR) == nWrite); | |
::FlushFileBuffers(hFile); | |
CloseHandle(hFile); | |
LeaveCriticalSection(&s_csLog); | |
} | |
// strPath目录必须以"\"分隔,且最后一个字符不能为分隔符 | |
bool Cx_SeaLog::CleanLogFile(const wstring& strPath, const int nTime /* = MAX_LOGFILE_TIME*/) | |
{ | |
UINT nCnt = 0; | |
bool bFind = true; | |
wstring strFindPath = strPath + L"\\*"; | |
// 清理日志文件时,要避免与写文件的操作冲突,需要加锁保护 | |
EnterCriticalSection(&s_csLog); | |
WIN32_FIND_DATA finddata; | |
HANDLE hFind = ::FindFirstFile(strFindPath.c_str(), &finddata); | |
if (INVALID_HANDLE_VALUE == hFind) | |
{ | |
return false; | |
} | |
do | |
{ | |
// 过滤当前目录与上级目录 | |
if (_tcscmp(finddata.cFileName, L".") == 0 | |
|| _tcscmp(finddata.cFileName, L"..") == 0) | |
{ | |
continue; | |
} | |
// 不处理嵌套目录 | |
if((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
== FILE_ATTRIBUTE_DIRECTORY) | |
{ | |
continue; | |
} | |
time_t modifiedTime; | |
FileTimeToDosTime(finddata.ftLastWriteTime, (ULONG*)&modifiedTime); | |
time_t curTime = ::time(NULL); | |
// 日志的最后修改时间距现在超过限定时间,则删除日志文件 | |
// ASSERT(curTime - modifiedTime > 0); | |
if (curTime - modifiedTime > MAX_LOGFILE_TIME) | |
{ | |
wstring strFullName = strPath + L"\\" + finddata.cFileName; | |
VERIFY(::DeleteFile(strFullName.c_str())); | |
} | |
} while(::FindNextFile(hFind, &finddata)); | |
FindClose(hFind); | |
LeaveCriticalSection(&s_csLog); | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment