1、/*/* 文件名称:write_log.cpp* 摘 要:此文件实现了普通WINDOWS程序中的日志功能* 主要有以下特点:* 1. 根据日期创建日志文件目录,每天的日志分别存放在不同的日志目录中;* 2. 日志内容分三种类型,根据不同需要,写不同的日志类型的日志文件,* 方便通过日志定位、分析问题;* 3. 函数经过比较好的封装,便于复用;* 待改进点:* 1. 为了方便,日志内容打印时使用了time函数,其精确度较低;* 2. 可将这些函数封装为一个日志类,或者动态库,使其更通用;* 3. 没有考虑跨平台情景,目前只使用于WINDOWS下* 4. 日志文件内容还可进一步改进,比如打印出当前
2、文件名与行号,使用日志功能* 更加实用;* 当前版本:1.0* 作 者:duanyongxing * 完成日期:2009年10月11日*/ /*/#ifndef _WRITELOG_H_#define _WRITELOG_H_#include “stdafx.h“#include #include #include #include #include #include #define _LOG_WRITE_STATE_ 1 /* 条件编 ,1:写日志,0:不写日志 */#define LOG_SUCCESS (0)#define LOG_FAILED (-1)#define LOG_BOOL_
3、TRUE (1)#define LOG_BOOL_FALSE (0)#define DWORD_NULL (0xFFFFFFFF)#define MAX_LOGTEXT_LEN (1024) /* 每行日志的 度*/#define MAX_FILE_PATH (255) /* 日志文件 的 度*/#define MAX_LOG_FILE_SIZE (512 * 1024) /* 日志文件内容的 度*/#define MAX_LOG_FILE_NAME_LEN (256) /* 日志文件名的 度*/#define LOG_TYPE_INFO 0 /* 日志类型: 类型*/#define LOG_
4、TYPE_ERROR 1 /* 日志类型: 类型*/#define LOG_TYPE_SYSTEM 2 /* 日志类型: 类型*/#define TEST_CASE_MAX_FILE_LEN (512) /* 函数中文件内容 度*/const char g_LogRootPath = “C:My_APPLOG“; /*日志文件根 , 用 定*/#pragma pack(push, 1)typedef struct tagLOG_DATA /* 日志内容 */char strDate11; /* 日期: 为如:2009-10-11*/char strTime9; /* 时 : 为如:16:10:
5、57*/unsigned int iType; /* 日志类型:3种:INFO(0)/ERROR(1)/SYSTEM(2)*/char strTextMAX_LOGTEXT_LEN; /*日志内容*/LOG_DATA, *LPLOG_DATA;#pragma pack(pop)int Create_LogDir(const char *pStrPath);int Create_LogFile(const char *pStrFile, int iPos);int IsFileExist(const char *pStrFile);int GetLogPath(char *pStrPath);D
6、WORD GetFileLenth(const char *pFile);int Write_Log_Text(LPLOG_DATA lpLogData);void Write_Log(unsigned int uiLogType, char *pstrFmt, .);void TestLogCase_One();int main(int argc, char* argv)Write_Log(LOG_TYPE_SYSTEM, “Program begin.“);TestLogCase_One();Write_Log(LOG_TYPE_SYSTEM, “Program end.“);return
7、 0;/* 函数名称:void TestLogCase_One()* : 的 函数, 文件* 用者:main* 数:* * 出数:* * :* void - * 作者: duanyongxing* 时 : 2009-10-11*/void TestLogCase_One()FILE *pFile = NULL;char *pFieldContent = NULL;char szFileName = “test_case.txt“;pFieldContent = (char *)malloc(TEST_CASE_MAX_FILE_LEN);if(NULL = pFieldContent)Writ
8、e_Log(LOG_TYPE_ERROR, “malloc memory failed,program exit!“);return;memset(pFieldContent, 0, TEST_CASE_MAX_FILE_LEN);Write_Log(LOG_TYPE_INFO, “malloc memory for pFiled successful,memory size is: %ld“,TEST_CASE_MAX_FILE_LEN);pFile = fopen(szFileName, “r“);if(NULL = pFile)fprintf(stderr, “open file fai
9、led.“);Write_Log(LOG_TYPE_ERROR, “Open file %s failed. program exit!“, szFileName);return;Write_Log(LOG_TYPE_INFO, “Open file %s successful.“, szFileName);fread(pFieldContent, 1, TEST_CASE_MAX_FILE_LEN, pFile);pFieldContentTEST_CASE_MAX_FILE_LEN -1 = 0;fclose(pFile);printf(“The file %s content is: %
10、sn“, szFileName, pFieldContent);Write_Log(LOG_TYPE_INFO, “The file %s content is: %sn“, szFileName, pFieldContent);/* 函数名称:void Write_Log(unsigned int uiLogType, char *pstrFmt, .)* :日志写函数,currency1 数* 用者:“需要写日志的方* 数:* unsigned iType - 日志类别* char *pstrFmt - 日志内容* . - currency1 数* 出数:* * :* void - * 作
11、者: duanyongxing* 时 : 2009-10-11*/void Write_Log(unsigned int uiLogType, char *pstrFmt, .)#if _LOG_WRITE_STATE_ /* 写日志与的编 */LOG_DATA data;time_t curTime;struct tm *mt;va_list v1;memset(va_start(v1, pstrFmt);_vsnprintf(data.strText, MAX_LOGTEXT_LEN, pstrFmt, v1);va_end(v1);data.iType = uiLogType;curTi
12、me = time(NULL);mt = localtime(strftime(data.strDate, sizeof(data.strDate), “%Y-%m-%d“, mt);strftime(data.strTime, sizeof(data.strTime), “%H:%m:%S“, mt);Write_Log_Text(#endif _LOG_WRITE_STATE_/* 函数名称:int GetLogPath(char *pStrPath)* :fi日志文件 * 用者:Write_Log_Text* 数:* * 出数:* char *pStrPath* :* int - LOG
13、_FAILED: fl * - LOG_SUCCESS: 成功* 作者: duanyongxing* 时 : 2009-10-11*/int GetLogPath(char *pStrPath)if(NULL = pStrPath)return LOG_FAILED;int iRet = 0;time_t curTime = time(NULL);struct tm *mt = localtime(/* 根据日期成文件名称*/sprintf(pStrPath, “%s%d%02d%02d“, g_LogRootPath, mt-tm_year + 1900,mt-tm_mon + 1, mt-
14、tm_mday);iRet = Create_LogDir(pStrPath);return iRet;/* 函数名称:int GetLogFileName(int iLogType, const char *pStrPath, char *pStrName)* :fi日志文件名* 用者:Write_Log_Text* 数:* int iLogType - 日志类型 3种:INFO(0)/ERROR(1)/SYSTEM(2)* const char *pStrPath - 日志 GetLogPath* 出数:* char *pStrName - 日志文件名* :* int - LOG_FAIL
15、ED: fl * - LOG_SUCCESS: 成功* 作者: duanyongxing* 时 : 2009-10-11*/int GetLogFileName(int iLogType, const char *pStrPath, char *pStrName)if(NULL = pStrPath)return LOG_FAILED;char szLogNameMAX_FILE_PATH;FILE *pFile = NULL;memset(szLogName, 0, MAX_FILE_PATH);switch (iLogType)case LOG_TYPE_INFO:sprintf(szLo
16、gName, “%sapp_info“, pStrPath);break;case LOG_TYPE_ERROR:sprintf(szLogName, “%sapp_error“, pStrPath);break;case LOG_TYPE_SYSTEM:sprintf(szLogName, “%sapp_system“, pStrPath);break;default:return LOG_FAILED;break;strcat(szLogName, “.log“);if(IsFileExist(szLogName)/* 如 文件 度 于 定的 度,创建一文件,”文件*/if(int)Get
17、FileLenth(szLogName) + 256 = MAX_LOG_FILE_SIZE)Create_LogFile(szLogName, 0);elseCreate_LogFile(szLogName, 0);sprintf(pStrName, “%s“, szLogName);return LOG_SUCCESS;/* 函数名称:int Create_LogDir(const char *pStrPath)* :创建日志存放 * 用者:GetLogPath* 数:* const char *pStrPath -用 定的根 * 出数:* * :* int - LOG_FAILED: f
18、l * - LOG_SUCCESS: 成功* 作者: duanyongxing* 时 : 2009-10-11*/int Create_LogDir(const char *pStrPath)if(NULL = pStrPath)return LOG_FAILED;int iRet = 0;char szSubMAX_FILE_PATH;char *pSub = NULL;int iIndex = 0;int iLen = 0;int bFind = 0;memset(szSub, 0, sizeof(MAX_FILE_PATH);/* 创建目录*/while(1)pSub = strchr(
19、pStrPath + iLen, );if(NULL = pSub)if(iLen = 0)return LOG_FAILED;iRet = CreateDirectory(pStrPath, NULL);if(0 = iRet)iRet = GetLastError();if(ERROR_ALREADY_EXISTS = iRet)return LOG_SUCCESS;return LOG_FAILED;return LOG_SUCCESS;elseif (!bFind)bFind = 1;elsememset(szSub, 0, sizeof(szSub);strncpy(szSub, p
20、StrPath, pSub - pStrPath);CreateDirectory(szSub, NULL);iLen = pSub - pStrPath + 1;return LOG_SUCCESS;/* 函数名称:int Create_LogFile(const char *pStrFile, int iPos)* :创建日志文件* 用者:GetLogFileName* 数:* const char *pStrFile -文件名* int iPos -文件 位 * 出数:* * :* int - LOG_FAILED: fl * - LOG_SUCCESS: 成功* 作者: duanyon
21、gxing* 时 : 2009-10-11*/int Create_LogFile(const char *pStrFile, int iPos)HANDLE hd = 0;int iRet = 0;if(NULL = pStrFile)return LOG_FAILED;hd = CreateFile(pStrFile, GENERIC_READ | GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);if(INVALID_HANDLE_VALUE = hd)return LOG_FAILED;if(DWORD_NUL
22、L = SetFilePointer(hd, iPos, NULL, FILE_BEGIN)return LOG_FAILED;iRet = SetEndOfFile(hd);CloseHandle(hd);return iRet;/* 函数名称:int IsFileExist(const char *pStrFile)* : 定的文件存在* 用者:GetLogFileName* 数:* const char *pStrFile -文件名* 出数:* * :* int - LOG_BOOL_FALSE: 不存在* - LOG_BOOL_TRUE: 存在* 作者: duanyongxing* 时
23、 : 2009-10-11*/int IsFileExist(const char *pStrFile)int iLen = 0;WIN32_FIND_DATA finddata;memset(HANDLE hd = FindFirstFile(pStrFile, if(INVALID_HANDLE_VALUE = hd)DWORD dwRet = GetLastError();if(ERROR_FILE_NOT_FOUND = dwRet | ERROR_PATH_NOT_FOUND = dwRet)return LOG_BOOL_FALSE;FindClose(hd);return LOG
24、_BOOL_TRUE;/* 函数名称:DWORD GetFileLenth(const char *pFile)* : 定的文件 * 用者:GetLogFileName* 数:* const char *pFile -文件名* 出数:* * :* DWORD - 文件 * 作者: duanyongxing* 时 : 2009-10-11*/DWORD GetFileLenth(const char *pFile)WIN32_FIND_DATA buff;HANDLE hd = NULL;memset(hd = FindFirstFile(pFile, FindClose(hd);return
25、(buff.nFileSizeHigh * MAXDWORD) + buff.nFileSizeLow;/* 函数名称:int Write_Log_Text(LPLOG_DATA lpLogData)* :写日志内容* 用者:Write_Log* 数:* LPLOG_DATA lpLogData -日志内容 * 出数:* * :* int - LOG_FAILED: fl * - LOG_SUCCESS: 成功* 作者: duanyongxing* 时 : 2009-10-11*/int Write_Log_Text(LPLOG_DATA lpLogData)char szFilePathMA
26、X_FILE_PATH;char szFileNameMAX_LOG_FILE_NAME_LEN;FILE *pFile = NULL;char szLogTextMAX_LOGTEXT_LEN;memset(szFilePath, 0, MAX_FILE_PATH);memset(szFileName, 0, MAX_LOG_FILE_NAME_LEN);memset(szLogText, 0, MAX_LOGTEXT_LEN);GetLogPath(szFilePath);GetLogFileName(lpLogData-iType, szFilePath, szFileName);pFile = fopen(szFileName, “a+“);if(NULL = pFile)return LOG_FAILED;sprintf(szLogText, “%s %s %sn“, lpLogData-strDate, lpLogData-strTime,lpLogData-strText);fwrite(szLogText, 1, strlen(szLogText), pFile);fclose(pFile);return LOG_SUCCESS;