C++写日志源代码分析,可实现根据日期自动创建文件夹、日志分类、文件大小控制等

            最近在做一个项目,使用C++写一个动态链接库(dll),里面需要有日志功能,于是参考网上的资料实现了C++写日志的功能。日志可以指定路径保存,也可以默认保存在当前可执行程序(exe)所在的文件夹。现在把源代码贴出来与大家共享,还请各位大神批评指正。

    头文件:writeLog.h

/************************************************************************/
#ifndef _WRITELOG_H
#define _WRITELOG_H

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <Windows.h>
#include <memory.h>

#define LOG_WRITE_STATE 1    /*写日志条件,1:写日志,0:不写日志*/

#define LOG_SUCCESS 0   /*写日志成功标志*/
#define LOG_FAILED (-1)  /*写日志失败标志*/

#define DWORD_NULL (0xFFFFFFFF)

#define MAX_LINE_LEN 1024  /*每行日志的最大长度*/
#define MAX_FILE_PATH 256  /*日志文件路径的最大长度*/
#define MAX_LOG_FILE_SIZE (512*1024)  /*日志文件内容的最大长度*/
#define MAX_LOG_NAME_LEN 256  /*日志文件名的最大长度*/

#define LOG_TYPE_INFO 0  /*日志类型:错误类型*/
#define LOG_TYPE_SYSTEM 1  /*日志类型:系统类型*/
#define LOG_TYPE_ERROR 2  /*日志类型:错误类型*/

/*日志内容结构体*/
struct logData
{
	char strDate[11];  /*日期:格式为2014-07-01*/
	char strTime[9];  /*时间,格式为20:12:06*/
	unsigned char logType;  /*日志类型:INFO(0),SYSTEM(1),ERROR(2)*/
	char logText[MAX_LINE_LEN];  /*每行的日志内容*/
};
#endif
    源文件:writeLog.cpp

/************************************************************************/
#include "writeLog.h"
#include <io.h>
#include <direct.h>

int writeLogText(logData *pLogData);  /*写日志内容*/
void writeLog(unsigned char type, char *pStrText);  /*写日志*/
int createLogDir(char *pStrPath);  /*创建保存日志的路径*/
int createLogFile(const char *pStrPath, int iPos);  /*创建保存日志的文件夹*/
bool IsFileExist(const char *pStrFile);  /*判断文件是否存在*/
int getLogPath(char *pStrPath);  /*获取日志的路径*/
DWORD getFileLen(const char *pFile);  /*获取文件长度*/
int getLogFileName(int logType, const char *pStrPath, char *pStrName);  /*获取日志文件名*/

/************************************************************************/
/* 
函数名称:int writeLogText(logData *pLogData)
说明:写日志内容
参数:pLogData是指向logData结构体的指针
返回值:LOG_SUCCESS(0)表示成功,LOG_FAILED(-1)表示失败
*/
/************************************************************************/
int writeLogText(logData *pLogData)
{
	char filePath[MAX_FILE_PATH];
	char fileName[MAX_LOG_NAME_LEN];
	FILE *pFile = NULL;
	char logText[MAX_LINE_LEN];
	memset(filePath, 0, MAX_FILE_PATH);
	memset(fileName, 0, MAX_LOG_NAME_LEN);
	memset(logText, 0, MAX_LINE_LEN);
	getLogPath(filePath);
	getLogFileName(pLogData->logType, filePath, fileName);
	//pFile = fopen(fileName, "a+");
	int r = fopen_s(&pFile, fileName, "a+");
	if(NULL == pFile)
		return LOG_FAILED;
	sprintf_s(logText, sizeof(logText), "%s %s %s\n", pLogData->strDate, pLogData->strTime, pLogData->logText);
	fwrite(logText, 1, strlen(logText), pFile);
	fclose(pFile);
	return LOG_SUCCESS;
}

/************************************************************************/
/* 
函数名称:void writeLog(unsigned char type, char *pStrText)
说明:写日志函数
参数:type:日志类型,pStrText:指向日志内容的指针
返回值:无
*/
/************************************************************************/
void writeLog(unsigned char type, char *pStrText)
{
	logData data;
	time_t currTime;
	struct tm *mt;
	memset(&data, 0, sizeof(logData));
	data.logType = type;
	strcpy(data.logText, pStrText);
	currTime = time(NULL);
	mt = localtime(&currTime);
	strftime(data.strDate, sizeof(data.strDate), "%Y-%m-%d", mt);
	strftime(data.strTime, sizeof(data.strTime), "%H:%M:%S", mt);
	writeLogText(&data);
}

/************************************************************************/
/* 
函数名:int createLogDir(char *pStrPath)
参数:pStrPath是用户指定的根路径
说明:创建日志存放路径
返回值:LOG_SUCCESS:成功
        LOG_FAILED:失败
*/
/************************************************************************/
int createLogDir(char *pStrPath)
{
	char *tag = NULL;
	for (tag = pStrPath;*tag != NULL;tag++)
	{
		if ('\\' == *tag)
		{
			char path[MAX_FILE_PATH];
			char buff[MAX_FILE_PATH];
			strcpy(buff, pStrPath);
			buff[strlen(pStrPath) - strlen(tag) + 1] = NULL;
			strcpy(path, buff);
			if (_access(path, 0) == -1)
			{
				int r = _mkdir(path);
				if (-1 == r)
				{
					return LOG_FAILED;
				}
			}
		}
	}
	return LOG_SUCCESS;
}

/************************************************************************/
/* 
函数名:int createLogFile(const char *pStrPath, int iPos)
参数:pStrPath:文件名,iPos:文件指针位置
说明:创建日志文件
返回值:LOG_SUCCESS:成功
        LOG_FAILED:失败
*/
/************************************************************************/
int createLogFile(const char *pStrPath, int iPos)
{
	HANDLE hd = 0;
	int iRet = 0;
	if (NULL == pStrPath)
	{
		return LOG_FAILED;
	}
	hd = CreateFile(pStrPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (INVALID_HANDLE_VALUE == hd)
	{
		return LOG_FAILED;
	}
	if (DWORD_NULL == SetFilePointer(hd, iPos, NULL, FILE_BEGIN))
	{
		return LOG_FAILED;
	}
	iRet = SetEndOfFile(hd);
	CloseHandle(hd);
	return iRet;
}

/************************************************************************/
/* 
函数名:bool IsFileExist(const char *pStrFile)
参数:pStrFile,文件名
说明:判断指定的文件是否存在
返回值:true:存在
        false:不存在
*/
/************************************************************************/
bool IsFileExist(const char *pStrFile)
{
	int iLen = 0;
	WIN32_FIND_DATA findData;
	memset(&findData, 0, sizeof(WIN32_FIND_DATA));
	HANDLE hd = FindFirstFile(pStrFile, &findData);
	if (INVALID_HANDLE_VALUE == hd)
	{
		DWORD dwRet = GetLastError();
		if (ERROR_FILE_NOT_FOUND == dwRet || ERROR_PATH_NOT_FOUND == dwRet)
		{
			return false;
		}
	}
	FindClose(hd);
	return true;
}

/************************************************************************/
/* 
函数名:int getLogPath(char *pStrPath)
参数:pStrPath,文件名
说明:获取日志文件路径
返回值:LOG_SUCCESS:成功
        LOG_FAILED:失败
*/
/************************************************************************/
int getLogPath(char *pStrPath)
{
	if (NULL == pStrPath)
	{
		return LOG_FAILED;
	}
	char currDir[MAX_FILE_PATH];// = "F:\\writelog";
	memset(currDir, 0, MAX_FILE_PATH);
	int iRet = 0;
	time_t currTime = time(NULL);
	struct tm *mt = localtime(&currTime);
	/*根据日期组成文件夹名*/
	GetModuleFileName(NULL, currDir, MAX_FILE_PATH);
	//(strrchr(currDir, '\\'))[1] = 0;
	int temp = 0;
	for (int i = sizeof(currDir);i > 0;i--)
	{
		if (currDir[i] == '\\')
		{
			temp = i;
			break;
		}
	}
	currDir[temp + 1] = 0;
	sprintf(pStrPath, "%s%d%02d%02d\\", currDir, mt->tm_year + 1900, mt->tm_mon + 1, mt->tm_mday);
	iRet = createLogDir(pStrPath);
	return iRet;
}

/********************************************************************* 
* 函数名称:DWORD getFileLen(const char *pFile)
* 说明:获取指定的文件大小 
* 输入参数: 
* const char *pFile --文件名 
* 返回值: 
* DWORD -- 文件大小 
*********************************************************************/  
DWORD getFileLen(const char *pFile) 
{
	WIN32_FIND_DATA data;
	HANDLE hd = NULL;
	memset(&data, 0, sizeof(WIN32_FIND_DATA));
	hd = FindFirstFile(pFile, &data);
	FindClose(hd);
	return (data.nFileSizeHigh * MAXDWORD) + data.nFileSizeLow;
}

/********************************************************************* 
* 函数名称:int getLogFileName(int logType, const char *pStrPath, char *pStrName); 
* 说明:获取日志文件名 
* 输入参数: 
* int logType         -- 日志类型 3种:INFO(0)/ERROR(1)/SYSTEM(2) 
* const char *pStrPath -- 日志路径 由getLogPath得到 
* 输出参数: 
* char *pStrName       -- 日志文件名 
* 返回值: 
* int -- LOG_FAILED: 失败 
*      -- LOG_SUCCESS: 成功 
*********************************************************************/
int getLogFileName(int logType, const char *pStrPath, char *pStrName)
{
	if (NULL == pStrPath)
	{
		return LOG_FAILED;
	}
	char logName[MAX_FILE_PATH];
	FILE *pFile = NULL;
	memset(logName, 0, MAX_FILE_PATH);
	switch(logType)
	{
	case LOG_TYPE_INFO:
		sprintf_s(logName, sizeof(logName), "%s\\dll_log_info", pStrPath);
		break;
	case LOG_TYPE_ERROR:
		sprintf_s(logName, sizeof(logName), "%s\\dll_log_error", pStrPath);
		break;
	case LOG_TYPE_SYSTEM:
		sprintf_s(logName, sizeof(logName), "%s\\dll_log_system", pStrPath);
		break;
	default:
		return LOG_FAILED;
		break;
	}
	strcat(logName, ".txt");
	if (IsFileExist(logName))
	{
		/*如果文件长度大于指定的最大长度,则重新创建一个文件覆盖原文件*/
		if ((int)getFileLen(logName) + 256 >= MAX_LOG_FILE_SIZE)
		{
			createLogFile(logName, 0);
		}
	}
	else
		createLogFile(logName, 0);
	sprintf(pStrName, "%s", logName);
	return LOG_SUCCESS;
}
//测试代码
int main()
{
	writeLog(LOG_TYPE_SYSTEM, "program begin.");
	return 0;
}



你可能感兴趣的:(C++,写日志)