最近在做一个项目,使用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;
}
版权声明:本文为u013149325原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。