原文来自:http://blog.sina.com.cn/s/blog_59b6af6901010nfh.html
修改Shenzhen 2016-9-10 把strypy、strcat等改成安全的strycpy_s、strycat_s等
ps:这个log功能过于简陋,凑合看着吧。
//可按日期生成多个日志, 还可分年月日频率生成文件名
//这个代码我用工业现场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
{
public:
LogFile(const char *szFileName = "Log.log"); //设定日志文件名
virtual ~LogFile();
const char * GetFileName(){ return _szFileName; }
void SetFileName(const char *szName); //修改文件名, 同时关闭上一个日志文件
bool IsOpen() { return _hFile != INVALID_HANDLE_VALUE; }
void Close();
void Log(LPCVOID lpBuffer, DWORD dwLength); //追加日志内容
void Log(const char *szText){ Log(szText, strlen(szText)); }
protected:
CRITICAL_SECTION _csLock;
char _szFileName[MAX_PATH + 1];
HANDLE _hFile;
bool OpenFile(); //打开文件, 指针到文件尾
DWORD Write(LPCVOID lpBuffer, DWORD dwLength);
virtual void WriteLog( LPCVOID lpBuffer, DWORD dwLength); //写日志, 可以扩展修改
void Lock() { ::EnterCriticalSection(&_csLock); }
void Unlock() { ::LeaveCriticalSection(&_csLock); }
private://屏蔽函数
LogFile(const LogFile&);
LogFile&operator = (const LogFile&);
};
class LogFileEx : public LogFile
{
public:
enum LOG_TYPE{YEAR = 0, MONTH = 1, DAY = 2};
LogFileEx(const char *szPath = ".", LOG_TYPE iType = MONTH);
~LogFileEx();
const char * GetPath(){ return _szPath; }
void Log(LPCVOID lpBuffer, DWORD dwLength);
void Log(const char *szText){ Log(szText, strlen(szText)); }
protected:
char _szPath[MAX_PATH + 1];
char _szLastDate[20];
int _iType;
void SetPath(const char *szPath);
private://屏蔽函数
LogFileEx(const LogFileEx&);
LogFileEx&operator = (const LogFileEx&);
};
#endif
#include "stdafx.h"
#include "Logfile.h"
//-----------------------------------------------------------------------------------------
LogFile::LogFile(const char *szFileName)//设定日志文件名
{
_hFile = INVALID_HANDLE_VALUE;
::InitializeCriticalSection(&_csLock);
SetFileName(szFileName);
}
//-----------------------------------------------------------------------------------------
LogFile::~LogFile()
{
::DeleteCriticalSection(&_csLock);
Close();
}
//-----------------------------------------------------------------------------------------
void LogFile::SetFileName(const char *szName)//修改文件名, 同时关闭上一个日志文件
{
Close();
memset(_szFileName, 0, MAX_PATH + 1);
strcpy_s(_szFileName, MAX_PATH + 1, szName);
}
//-----------------------------------------------------------------------------------------
bool LogFile::OpenFile()//打开文件, 指针到文件尾
{
if(IsOpen())
return true;
if(strcmp(_szFileName, "") == 0)
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 LogFile::Write(LPCVOID lpBuffer, DWORD dwLength)
{
DWORD dwWriteLength = 0;
if(IsOpen())
WriteFile(_hFile, lpBuffer, dwLength, &dwWriteLength, NULL);
return dwWriteLength;
}
//-----------------------------------------------------------------------------------------
void LogFile::WriteLog( LPCVOID lpBuffer, DWORD dwLength)//写日志, 可以扩展修改
{
char temp[21] = {0};
DWORD dwWriteLength;
if(IsOpen())
{
time_t now;
time(&now);
tm timeInfo;
localtime_s(&timeInfo, &now); //转换成tm结构
strftime(temp, sizeof(temp), "%Y-%m-%d %H:%M:%S", &timeInfo);
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 LogFile::Close()
{
if(IsOpen())
{
CloseHandle(_hFile);
_hFile = INVALID_HANDLE_VALUE;
}
}
//-----------------------------------------------------------------------------------------
void LogFile::Log(LPCVOID lpBuffer, DWORD dwLength)//追加日志内容
{
assert(lpBuffer);
__try
{
Lock();
if(!OpenFile())
return;
WriteLog(lpBuffer, dwLength);
}
__finally
{
Unlock();
}
}
//LogFileEx**********************************************************************************
LogFileEx::LogFileEx(const char *szPath, LOG_TYPE iType)
{
memset(_szPath, 0, sizeof(_szPath));
SetPath(szPath);
_iType = iType;
memset(_szLastDate, 0, sizeof(_szLastDate));
}
//---------------------------------------------------------------------------------
LogFileEx::~LogFileEx()
{
}
//---------------------------------------------------------------------------------
void LogFileEx::Log(LPCVOID lpBuffer, DWORD dwLength)
{
assert(lpBuffer);;
static const char format[3][10] = {"%Y", "%Y-%m", "%Y%m%d"};
__try
{
Lock();
char temp[20] = {0};
time_t now = time(NULL);
tm timeInfo;
localtime_s(&timeInfo, &now); //转成tm结构
strftime(temp, sizeof(temp), format[_iType], &timeInfo);
if(strcmp(_szLastDate, temp) != 0)//更换文件名
{
int len = sizeof(_szFileName);
strcpy_s(_szFileName, len, _szPath); len -= strlen(_szPath);
strcat_s(_szFileName, len, "//"); len -= 2;
strcat_s(_szFileName, len, temp); len -= sizeof(temp);
strcat_s(_szFileName, len, ".log"); len -= 4;
strcpy_s(_szLastDate, sizeof(_szLastDate), temp);
Close();
}
if(!OpenFile())
return;
WriteLog(lpBuffer, dwLength);
}
__finally
{
Unlock();
}
}
//---------------------------------------------------------------------------------
void LogFileEx::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)
{
strcpy_s(temp, sizeof(temp), szPath);
strcat_s(temp, sizeof(temp), " Create Fail. Exit Now! Error ID :");
_ltoa_s(GetLastError(), temp + strlen(temp), 20, 10);
MessageBox(NULL, temp, "Class LogFileEx", MB_OK);
exit(1);
}
else
{
GetFullPathName(szPath, MAX_PATH, temp, NULL);
strcpy_s(_szPath, sizeof(_szPath), temp);
}
}
// Main.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "Common/Logfile.h"
int _tmain(int argc, _TCHAR* argv[])
{
LogFileEx log("../Debug/Logfiles");
for (int i=0; i<1000000; ++i)
log.Log("4646456015555555555555555555555555555555555555");
printf("已完成");
getchar();
return 0;
}