Skip to content

Instantly share code, notes, and snippets.

@thinkhy
Created March 27, 2011 16:20
Show Gist options
  • Save thinkhy/889338 to your computer and use it in GitHub Desktop.
Save thinkhy/889338 to your computer and use it in GitHub Desktop.
A Log implement in Win32 C++
#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