牵着老婆满街逛

严以律己,宽以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

撰写日志类

/*
Log File Library(WIN98/NT/2000) 

Compile by: BC++ 5; C++ BUILDER; VC++; VC.NET; 

copyright(c) 2004.5 - 2005.3  llbird wushaojian@21cn.com 
http://blog.csdn.net/wujian53

*/

/*
Use:
//这个代码我用工业现场24X7值守的程序纪录各种信息, 简单易用;
//一般用一个全局日志对象, 有临界排斥可以多线程安全使用。
//有两个类
class LogFile;//用户定义日志文件名
class LogFileEx;//有日志文件名自动生成功能 , 可分年月日频率生成文件名, 可指定日志存放的目录

LogFile gLog("My.Log");
gLog.Log("test", 4);//记录日志
gLog.Log("系统启动");

LogFileEx gLog(".", LogFileEx :: YEAR);//一年生成一个日志文件
LogFileEx gLog(".\\Log", LogFileEx :: MONTH);//一月生成一个日志文件
LogFileEx gLog(".\\Log", LogFileEx :: DAY);//一天生成一个日志文件
//注意日志所属目录创建失败会自动退出, 请注意目录的合法性, 文件生成频率看情况掌握
//24小时运行的程序可以每天生成一个日志文件, 以免内容过多
*/


#ifndef _LOGFILE_H
#define  _LOGFILE_H

#include 
< assert.h >
#include 
< time.h >
#include 
< stdio.h >
#include 
< windows.h >

class  LogFile
{
protected :

 CRITICAL_SECTION _csLock;
 
char   *  _szFileName;
 HANDLE _hFile;

 
bool  OpenFile() // 打开文件, 指针到文件尾
  {
  
if (IsOpen())
   
return   true ;

  
if ( ! _szFileName)
   
return   false ;

  _hFile 
=   CreateFile(
   _szFileName, 
   GENERIC_WRITE,
   FILE_SHARE_READ 
|  FILE_SHARE_WRITE,
   NULL,
   OPEN_EXISTING,
   FILE_ATTRIBUTE_NORMAL,
   NULL 
  );

  
if ( ! IsOpen()  &&  GetLastError()  ==   2 ) // 打开不成功, 且因为文件不存在, 创建文件
   _hFile  =   CreateFile(
    _szFileName, 
    GENERIC_WRITE,
    FILE_SHARE_READ 
|  FILE_SHARE_WRITE,
    NULL,
    OPEN_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL 
   );  

  
if (IsOpen())
   SetFilePointer(_hFile, 
0 , NULL, FILE_END);

  
return  IsOpen();
 }


 DWORD Write(LPCVOID lpBuffer, DWORD dwLength)
 
{
  DWORD dwWriteLength 
=   0 ;

  
if (IsOpen())
   WriteFile(_hFile, lpBuffer, dwLength, 
& dwWriteLength, NULL);

  
return  dwWriteLength;
 }


 
virtual   void  WriteLog( LPCVOID lpBuffer, DWORD dwLength) // 写日志, 可以扩展修改
  {
  time_t now;
  
char  temp[ 21 ];
  DWORD dwWriteLength;

  
if (IsOpen())
  
{
   time(
& now);
   strftime(temp, 
20 " %Y-%m-%d %H:%M:%S " , localtime( & now));

   WriteFile(_hFile, 
" \xd\xa#----------------------------- " 32 & dwWriteLength, NULL);
   WriteFile(_hFile, temp, 
19 & dwWriteLength, NULL);
   WriteFile(_hFile, 
" -----------------------------#\xd\xa " 32 & dwWriteLength, NULL);
   WriteFile(_hFile, lpBuffer, dwLength, 
& dwWriteLength, NULL);
   WriteFile(_hFile, 
" \xd\xa " 2 & dwWriteLength, NULL);
   
   FlushFileBuffers(_hFile);

  }

 }


 
void  Lock()   { ::EnterCriticalSection( & _csLock); }
 
void  Unlock()  { ::LeaveCriticalSection( & _csLock); }
 
public :
  
 LogFile(
const   char   * szFileName  =   " Log.log " ) // 设定日志文件名
  {
  _szFileName 
=  NULL;
  _hFile 
=  INVALID_HANDLE_VALUE;
  ::InitializeCriticalSection(
& _csLock);

  SetFileName(szFileName);
 }


 
virtual   ~ LogFile()
 
{
  ::DeleteCriticalSection(
& _csLock);
  Close();

  
if (_szFileName)
   delete []_szFileName;
 }

 
 
const   char   *  GetFileName()
 
{
  
return  _szFileName;
 }


 
void  SetFileName( const   char   * szName) // 修改文件名, 同时关闭上一个日志文件
  {
  assert(szName);

  
if (_szFileName)
   delete []_szFileName;

  Close();

  _szFileName 
=   new   char [strlen(szName)  +   1 ];
  assert(_szFileName);
  strcpy(_szFileName, szName);
 }


 
bool  IsOpen()
 
{
  
return  _hFile  !=  INVALID_HANDLE_VALUE;
 }


 
void  Close()
 
{
  
if (IsOpen())
  
{
   CloseHandle(_hFile);
   _hFile 
=  INVALID_HANDLE_VALUE;
  }

 }


 
void  Log(LPCVOID lpBuffer, DWORD dwLength) // 追加日志内容
  {
  assert(lpBuffer);
  __try
  
{
   Lock();

   
if ( ! OpenFile())
    
return ;

   WriteLog(lpBuffer, dwLength);
  }

  __finally
  
{
   Unlock();
  }
 
 }


 
void  Log( const   char   * szText)
 
{
  Log(szText, strlen(szText));
 }


private : // 屏蔽函数

 LogFile(
const  LogFile & );
 LogFile
& operator   =  ( const  LogFile & );
}
;

class  LogFileEx :  public  LogFile
{
protected :

 
char   * _szPath;
 
char  _szLastDate[ 9 ];
 
int  _iType;

 
void  SetPath( const   char   * szPath)
 
{
  assert(szPath);

  WIN32_FIND_DATA wfd;
  
char  temp[MAX_PATH  +   1 =   { 0 } ;

  
if (FindFirstFile(szPath,  & wfd)  ==  INVALID_HANDLE_VALUE  &&  CreateDirectory(szPath, NULL)  ==   0 )
  
{
   strcat(strcpy(temp, szPath), 
"  Create Fail. Exit Now! Error ID : " );
   ltoa(GetLastError(), temp 
+  strlen(temp),  10 );
   MessageBox(NULL, temp, 
" Class LogFileEx " , MB_OK);
   exit(
1 );
  }

  
else
  
{
   GetFullPathName(szPath, MAX_PATH, temp, NULL);
   _szPath 
=   new   char [strlen(temp)  +   1 ];
   assert(_szPath);
   strcpy(_szPath, temp);
  }

 }


public :

 
enum  LOG_TYPE {YEAR  =   0 , MONTH  =   1 , DAY  =   2 } ;

 LogFileEx(
const   char   * szPath  =   " . " , LOG_TYPE iType  =  MONTH)
 
{
  _szPath 
=  NULL;
  SetPath(szPath);
  _iType 
=  iType;
  memset(_szLastDate, 
0 9 );
 }


 
~ LogFileEx()
 
{
  
if (_szPath)
   delete []_szPath;
 }


 
const   char   *  GetPath()
 
{
  
return  _szPath;
 }


 
void  Log(LPCVOID lpBuffer, DWORD dwLength)
 
{
  assert(lpBuffer);

  
char  temp[ 10 ];
  
static   const   char  format[ 3 ][ 10 =   { " %Y " " %Y-%m " " %Y%m%d " } ;
  
  __try
  
{
   Lock();
   
   time_t now 
=  time(NULL);

   strftime(temp, 
9 , format[_iType], localtime( & now));

   
if (strcmp(_szLastDate, temp)  !=   0 ) // 更换文件名
    {
    strcat(strcpy(_szFileName, _szPath), 
" \\ " );
    strcat(strcat(_szFileName, temp), 
" .log " );
    strcpy(_szLastDate, temp);
    Close();
   }


   
if ( ! OpenFile())
    
return ;
   
   WriteLog(lpBuffer, dwLength);
  }

  __finally
  
{
   Unlock();
  }

 }


 
void  Log( const   char   * szText)
 
{
  Log(szText, strlen(szText));
 }


private : // 屏蔽函数

 LogFileEx(
const  LogFileEx & );
 LogFileEx
& operator   =  ( const  LogFileEx & );

}
;

#endif


posted on 2006-04-17 16:59 杨粼波 阅读(1564) 评论(1)  编辑 收藏 引用

评论

# re: 撰写日志类 2006-04-25 17:02 hgwolf

代码写得不错,收藏了
hgwolf@263.net  回复  更多评论   


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理