一个经典的C++日志类

转自:http://www.zaoxue.com/article/tech-73193.htm

 

可按日期生成多个日志, 还可分年月日频率生成文件名

 

=====================================================================

 

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

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

copyright(c) 2004.5 - 2005.3  llbird [email protected] 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
#include
#include
#include

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

 

你可能感兴趣的:(C/C++)