心静自然凉~

一杯清茶、二盏淡酒、邀三五知己,诉七八句心语,道九分珍重,怀十分真诚,或伤感、或快乐,无现实之隔阂 、无世俗之势利,如此人生,不亦乐乎!

导航

CLog3 写日志的类

Posted on 2008-01-02 22:25  Leo.Zhu  阅读(1494)  评论(0编辑  收藏  举报

开始我的第一个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

/* 一个写log的类
时间 :2008-1-2
版本 :1.0.0.0
作者 :Karl.zhu
*/

#pragma once

#include 
<afxmt.h>
// CLog3 命令目标

class CLog3
{
public:
    CLog3();
    
void Init(CString FilePath,CString FileName);
    
virtual ~CLog3();

public :
    CString            m_FilePath;
    CString            m_FileName;
    DWORD                m_Fileday;
    CFile            m_File;

    HANDLE            m_processStopHandle,m_processSignalHandle,m_processThreadHandle;

    CStringList        m_messageQueue;
    CMutex            m_mutex;

    
static void LogProcessorThread(LPVOID data);

    
void QueueMessage(CString szLogEntry);
    
void StartLog();
    
void StopLog();
    
void CrateLog(CString csFilePath,CString csFileName);



}
;




CLog3.cpp

// 
//
/* 一个写log的类
时间 :2008-1-2
版本 :1.0.0.0
作者 :Karl.zhu
*/

#include 
"stdafx.h"
#include 
"Log3Demo.h"
#include 
"Log3.h"

#include 
<process.h>

// CLog3

CLog3::CLog3()
{
    

}

void CLog3::Init(CString FilePath,CString FileName)
{
    m_FilePath 
= FilePath;
    m_FileName 
= FileName;
}

CLog3::
~CLog3()
{

}



// CLog3 成员函数

void CLog3::CrateLog(CString csFilePath,CString csFileName)
{
    
try
    
{
        
this->m_mutex.Lock();

        CFileFind find ;
        
if (!find.FindFile(csFilePath))
        
{
            CreateDirectory(csFilePath,NULL);
        }


        CString filename,fileexe;

        
int Where = csFileName.ReverseFind(_T('.'));
        
if (Where != -1)
        
{
            filename 
= csFileName.Left(Where);
            fileexe 
= csFileName.Right(csFileName.GetLength() - Where - 1);
        }

        
else
        
{
            filename 
= csFileName;
            fileexe 
= "";
        }


        CTime now_time ;
        SYSTEMTIME tm;
        GetLocalTime(
&tm);
        CString day;
        day.Format(_T(
"_%02d"),tm.wDay);

        CString FileFullPath;
        FileFullPath.Format(_T(
"%s\\%s%s.%s"),csFilePath,filename,day,fileexe);


        
if (m_File.m_hFile != CFile::hFileNull)
        
{
            m_File.Close();
            
        }

        
            
if (!find.FindFile(FileFullPath,NULL))
            
{
                
//没有找到
                if (!m_File.Open(FileFullPath,CFile::modeCreate|CFile::modeReadWrite| CFile::shareDenyNone))
                
{
                    AfxMessageBox(_T(
"Open File Error"));
                }

                
this->m_Fileday = tm.wDay;
            }

            
else
            
{

                
//找到
                WIN32_FIND_DATA FindFileData;
                FindClose(FindFirstFile(FileFullPath,
&FindFileData));
                SYSTEMTIME csCreateTime;
                FileTimeToSystemTime(
&FindFileData.ftCreationTime,&csCreateTime);

                
if (tm.wDay == csCreateTime.wDay && tm.wMonth == csCreateTime.wMonth && tm.wYear == csCreateTime.wYear)
                
{
                    
if(!m_File.Open(FileFullPath,CFile::modeReadWrite| CFile::shareDenyNone))
                    
{
                        AfxMessageBox(_T(
"Open Log Error"));
                    }

                    
this->m_Fileday = tm.wDay;

                }

                
else
                
{
                    
if (!m_File.Open(FileFullPath,CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone))
                    
{
                        AfxMessageBox(_T(
"Open Log Error"));
                    }

                    
else{
                        FILETIME  ft;
                        SystemTimeToFileTime(
&tm,&ft);
                        SetFileTime(m_File.m_hFile,
&ft,&ft,&ft);
                        
this->m_Fileday = tm.wDay;

                    }

                }

                
//memset(&FileInfo,0,sizeof(FILE_INFO));
            }

            
        
    }

    
catch ()
    
{
        DWORD lastError 
= GetLastError();
        CString Err ;
        Err.Format(_T(
"%d"),lastError);
        AfxMessageBox(Err);
    }

    
this->m_mutex.Unlock();

}




void CLog3::StartLog()
{
    
    CrateLog(m_FilePath,m_FileName);
    
this->m_processStopHandle = CreateEvent(NULL,TRUE,FALSE,NULL);
    
this->m_processSignalHandle = CreateEvent(NULL,TRUE,FALSE,NULL);

    m_processThreadHandle 
= HANDLE(_beginthread(LogProcessorThread, 0this));
    
if(m_processThreadHandle != LPVOID(-1))
    
{
        AfxMessageBox(_T(
"Log Thread OK"));

    }

    
else
    
{
        AfxMessageBox(_T(
"Log Thread Faild"));
    }


    
}

void CLog3::StopLog()
{
    SetEvent(
this->m_processStopHandle);
}

void CLog3::LogProcessorThread(LPVOID data)
{
    CLog3 
*me = (CLog3 *) data;
    BOOL         bStop 
= FALSE;
    DWORD         dwWritten;
    HANDLE         hHandleArray[
2];

    ASSERT(me);

    hHandleArray[
0= me->m_processStopHandle;
    hHandleArray[
1= me->m_processSignalHandle;

    CString csData;

    
while (bStop == FALSE)
    
{
        
switch (WaitForMultipleObjects(2, hHandleArray, FALSE, INFINITE))
        
{
        
case WAIT_OBJECT_0:
            bStop 
= TRUE;
            
break;

        
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)
            
{
                me
->CrateLog(me->m_FilePath,me->m_FileName);
            }

            me
->m_mutex.Lock();
            
            
while (me->m_messageQueue.GetCount())
            
{
                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
                me->m_mutex.Unlock();

                
//    Seek to the end of the file
                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));
                

                CHAR 
* endline ="\r\n";
                me
->m_File.Write(endline,strlen(endline));
                me
->m_mutex.Lock();
            }


            
//    Now unlock it again
            me->m_mutex.Unlock();

            
//    Force output to disk
            me->m_File.Flush();
            ResetEvent(me
->m_processSignalHandle);
            
break;
        }

    }


    me
->m_File.Close();

AfxMessageBox(_T(
"end File"));

_endthread();
}


void CLog3::QueueMessage(CString szLogEntry)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    ASSERT(szLogEntry);
    ASSERT(AfxIsValidString(szLogEntry));

    
//    Lock the object for the addhead call
    
//    (must be fast once we get the lock).
    m_mutex.Lock();
    m_messageQueue.AddHead(szLogEntry);
    m_mutex.Unlock();

    
//    Now tell our processing thread there's 
    
//    new stuff to write
    SetEvent(m_processSignalHandle);

}


这个算是我第一个vc的code,可能也存在什么不妥之处,读者们见笑了。

Demo下载