开始我的第一个vc模块的设计。
这个是一个vc的写日志的类,为什么叫CLog3...因为之前有两版写log的类,但是都是用C#写的,所以这个vc写的就叫CLog3吧。
功能只是简单模拟C#中的写Log的方法的设计。
设计思路:
因为在程序运行过程中, 需要记录一些信息到log中, 同时要尽量减少对主处理模块的影响,减少i|o的操作,所以CLog3中设计的思路为自己创建一个Thread,该Thread会获取一个队列中的讯息,当要写一个讯息的时候, 将要写的信息添加到队列中,并通知Thread获取队列中的资料,写入已经打开的文件中。
因为在StartLog的时候,就已经将一个CFile对象打开了,所以减少了写是在Open的操作。
而调用方只是将要写的log扔到队列中,然后就可以继续处理自己的事情了,不用等待log写完后在处理,减少了对主模块的影响。
该开发环境是windows 2003 + vc.net 2005, 因为vc.net 2005中默认开启了Unicode 的模式,所以要写汉字到文件需要将CString转换成char * ,祥见: http://www.cnblogs.com/zhucl1006/archive/2008/01/02/1023380.html
Clog3.h
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//* 一个写log的类
时间 :2008-1-2
版本 :1.0.0.0
作者 :Karl.zhu
*/
#pragma once
![](/Images/OutliningIndicators/None.gif)
#include <afxmt.h>
// CLog3 命令目标
![](/Images/OutliningIndicators/None.gif)
class CLog3
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
CLog3();
void Init(CString FilePath,CString FileName);
virtual ~CLog3();
![](/Images/OutliningIndicators/InBlock.gif)
public :
CString m_FilePath;
CString m_FileName;
DWORD m_Fileday;
CFile m_File;
![](/Images/OutliningIndicators/InBlock.gif)
HANDLE m_processStopHandle,m_processSignalHandle,m_processThreadHandle;
![](/Images/OutliningIndicators/InBlock.gif)
CStringList m_messageQueue;
CMutex m_mutex;
![](/Images/OutliningIndicators/InBlock.gif)
static void LogProcessorThread(LPVOID data);
![](/Images/OutliningIndicators/InBlock.gif)
void QueueMessage(CString szLogEntry);
void StartLog();
void StopLog();
void CrateLog(CString csFilePath,CString csFileName);
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
CLog3.cpp
//
//
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//* 一个写log的类
时间 :2008-1-2
版本 :1.0.0.0
作者 :Karl.zhu
*/
#include "stdafx.h"
#include "Log3Demo.h"
#include "Log3.h"
![](/Images/OutliningIndicators/None.gif)
#include <process.h>
![](/Images/OutliningIndicators/None.gif)
// CLog3
![](/Images/OutliningIndicators/None.gif)
CLog3::CLog3()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
}
void CLog3::Init(CString FilePath,CString FileName)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
m_FilePath = FilePath;
m_FileName = FileName;
}
CLog3::~CLog3()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
// CLog3 成员函数
![](/Images/OutliningIndicators/None.gif)
void CLog3::CrateLog(CString csFilePath,CString csFileName)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
try
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this->m_mutex.Lock();
![](/Images/OutliningIndicators/InBlock.gif)
CFileFind find ;
if (!find.FindFile(csFilePath))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
CreateDirectory(csFilePath,NULL);
}
![](/Images/OutliningIndicators/InBlock.gif)
CString filename,fileexe;
![](/Images/OutliningIndicators/InBlock.gif)
int Where = csFileName.ReverseFind(_T('.'));
if (Where != -1)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
filename = csFileName.Left(Where);
fileexe = csFileName.Right(csFileName.GetLength() - Where - 1);
}
else
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
filename = csFileName;
fileexe = "";
}
![](/Images/OutliningIndicators/InBlock.gif)
CTime now_time ;
SYSTEMTIME tm;
GetLocalTime(&tm);
CString day;
day.Format(_T("_%02d"),tm.wDay);
![](/Images/OutliningIndicators/InBlock.gif)
CString FileFullPath;
FileFullPath.Format(_T("%s\\%s%s.%s"),csFilePath,filename,day,fileexe);
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
if (m_File.m_hFile != CFile::hFileNull)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
m_File.Close();
}
if (!find.FindFile(FileFullPath,NULL))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//没有找到
if (!m_File.Open(FileFullPath,CFile::modeCreate|CFile::modeReadWrite| CFile::shareDenyNone))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
AfxMessageBox(_T("Open File Error"));
}
this->m_Fileday = tm.wDay;
}
else
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
//找到
WIN32_FIND_DATA FindFileData;
FindClose(FindFirstFile(FileFullPath,&FindFileData));
SYSTEMTIME csCreateTime;
FileTimeToSystemTime(&FindFileData.ftCreationTime,&csCreateTime);
![](/Images/OutliningIndicators/InBlock.gif)
if (tm.wDay == csCreateTime.wDay && tm.wMonth == csCreateTime.wMonth && tm.wYear == csCreateTime.wYear)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(!m_File.Open(FileFullPath,CFile::modeReadWrite| CFile::shareDenyNone))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
AfxMessageBox(_T("Open Log Error"));
}
this->m_Fileday = tm.wDay;
![](/Images/OutliningIndicators/InBlock.gif)
}
else
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (!m_File.Open(FileFullPath,CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
AfxMessageBox(_T("Open Log Error"));
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
else
{
FILETIME ft;
SystemTimeToFileTime(&tm,&ft);
SetFileTime(m_File.m_hFile,&ft,&ft,&ft);
this->m_Fileday = tm.wDay;
![](/Images/OutliningIndicators/InBlock.gif)
}
}
//memset(&FileInfo,0,sizeof(FILE_INFO));
}
}
catch (
)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
DWORD lastError = GetLastError();
CString Err ;
Err.Format(_T("%d"),lastError);
AfxMessageBox(Err);
}
this->m_mutex.Unlock();
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
void CLog3::StartLog()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CrateLog(m_FilePath,m_FileName);
this->m_processStopHandle = CreateEvent(NULL,TRUE,FALSE,NULL);
this->m_processSignalHandle = CreateEvent(NULL,TRUE,FALSE,NULL);
![](/Images/OutliningIndicators/InBlock.gif)
m_processThreadHandle = HANDLE(_beginthread(LogProcessorThread, 0, this));
if(m_processThreadHandle != LPVOID(-1))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
AfxMessageBox(_T("Log Thread OK"));
![](/Images/OutliningIndicators/InBlock.gif)
}
else
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
AfxMessageBox(_T("Log Thread Faild"));
}
![](/Images/OutliningIndicators/InBlock.gif)
}
void CLog3::StopLog()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
SetEvent(this->m_processStopHandle);
}
void CLog3::LogProcessorThread(LPVOID data)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CLog3 *me = (CLog3 *) data;
BOOL bStop = FALSE;
DWORD dwWritten;
HANDLE hHandleArray[2];
![](/Images/OutliningIndicators/InBlock.gif)
ASSERT(me);
![](/Images/OutliningIndicators/InBlock.gif)
hHandleArray[0] = me->m_processStopHandle;
hHandleArray[1] = me->m_processSignalHandle;
![](/Images/OutliningIndicators/InBlock.gif)
CString csData;
![](/Images/OutliningIndicators/InBlock.gif)
while (bStop == FALSE)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
switch (WaitForMultipleObjects(2, hHandleArray, FALSE, INFINITE))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case WAIT_OBJECT_0:
bStop = TRUE;
break;
![](/Images/OutliningIndicators/InBlock.gif)
case WAIT_OBJECT_0 + 1:
// Lock the queue to get the count and the next entry
SYSTEMTIME tm1;
GetLocalTime(&tm1);
if (me->m_Fileday != tm1.wDay)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
me->CrateLog(me->m_FilePath,me->m_FileName);
}
me->m_mutex.Lock();
while (me->m_messageQueue.GetCount())
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
csData = me->m_messageQueue.RemoveTail();
SYSTEMTIME tm;
GetLocalTime(&tm);
CString csFullData;
csFullData.Format(_T("%02d:%02d:%02d[%03d] %s"),tm.wHour,tm.wMinute,tm.wSecond,tm.wMilliseconds,csData);
// Now unlock the queue while we write![](https://www.cnblogs.com/Images/dot.gif)
me->m_mutex.Unlock();
![](/Images/OutliningIndicators/InBlock.gif)
// Seek to the end of the file![](https://www.cnblogs.com/Images/dot.gif)
me->m_File.SeekToEnd();
DWORD leg = WideCharToMultiByte(CP_OEMCP,NULL,csFullData,-1,NULL,0,NULL,FALSE);
CHAR strchar [5000];
WideCharToMultiByte(CP_OEMCP,NULL,csFullData,-1,strchar,leg,NULL,FALSE);
me->m_File.Write(strchar,strlen(strchar));
![](/Images/OutliningIndicators/InBlock.gif)
CHAR * endline ="\r\n";
me->m_File.Write(endline,strlen(endline));
me->m_mutex.Lock();
}
![](/Images/OutliningIndicators/InBlock.gif)
// Now unlock it again
me->m_mutex.Unlock();
![](/Images/OutliningIndicators/InBlock.gif)
// Force output to disk![](https://www.cnblogs.com/Images/dot.gif)
me->m_File.Flush();
ResetEvent(me->m_processSignalHandle);
break;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
me->m_File.Close();
![](/Images/OutliningIndicators/InBlock.gif)
AfxMessageBox(_T("end File"));
![](/Images/OutliningIndicators/InBlock.gif)
_endthread();
}
![](/Images/OutliningIndicators/None.gif)
void CLog3::QueueMessage(CString szLogEntry)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
![](/Images/OutliningIndicators/InBlock.gif)
ASSERT(szLogEntry);
ASSERT(AfxIsValidString(szLogEntry));
![](/Images/OutliningIndicators/InBlock.gif)
// Lock the object for the addhead call![](https://www.cnblogs.com/Images/dot.gif)
// (must be fast once we get the lock).
m_mutex.Lock();
m_messageQueue.AddHead(szLogEntry);
m_mutex.Unlock();
![](/Images/OutliningIndicators/InBlock.gif)
// Now tell our processing thread there's
// new stuff to write![](https://www.cnblogs.com/Images/dot.gif)
SetEvent(m_processSignalHandle);
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/None.gif)
这个算是我第一个vc的code,可能也存在什么不妥之处,读者们见笑了。
Demo下载