最近在做一个项目,使用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; }