Linux教程網
- /************************************************************************/
- /*
- * 文件名稱:write_log.cpp
- * 摘 要:此文件實現了普通WINDOWS程序中的日志功能
- * 主要有以下特點:
- * 1. 根據日期創建日志文件目錄,每天的日志分別存放在不同的日志目錄中;
- * 2. 日志內容分三種類型,根據不同需要,寫不同的日志類型的日志文件,
- * 方便通過日志定位、分析問題;
- * 3. 函數經過比較好的封裝,便於復用;
- * 待改進點:
- * 1. 為了方便,日志內容打印時使用了time函數,其精確度較低;
- * 2. 可將這些函數封裝為一個日志類,或者動態庫,使其更通用;
- * 3. 沒有考慮跨平台情景,目前只使用於WINDOWS下
- * 4. 日志文件內容還可進一步改進,比如打印出當前文件名與行號,使用日志功能
- * 更加實用;
- *
- * 當前版本:1.0
- * 作 者:duanyongxing
- * 完成日期:2009年10月11日
- */
- /************************************************************************/
- #ifndef __WRITELOG_H__
- #define __WRITELOG_H__
- #include "stdafx.h"
- #include <time.h>
- #include <memory.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <windows.h>
- #define _LOG_WRITE_STATE_ 1 /* 條件編譯開關,1:寫日志,0:不寫日志 */
- #define LOG_SUCCESS (0)
- #define LOG_FAILED (-1)
- #define LOG_BOOL_TRUE (1)
- #define LOG_BOOL_FALSE (0)
- #define DWORD_NULL (0xFFFFFFFF)
- #define MAX_LOGTEXT_LEN (2048) /* 每行日志的最大長度*/
- #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_TYPE_ERROR 1 /* 日志類型: 錯誤類型*/
- #define LOG_TYPE_SYSTEM 2 /* 日志類型: 系統類型*/
- #define TEST_CASE_MAX_FILE_LEN (1024) /* 測試函數中文件內容最大長度*/
- const char g_LogRootPath[] = "C://My_APPLOG"; /*日志文件根路徑,由用戶指定*/
- #pragma pack(push, 1)
- typedef struct tagLOG_DATA /* 日志內容結構體*/
- {
- char strDate[11]; /* 日期:格式為如:2009-10-11*/
- char strTime[9]; /* 時間:格式為如:16:10:57*/
- unsigned int iType; /* 日志類型:3種:INFO(0)/ERROR(1)/SYSTEM(2)*/
- char strText[MAX_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);
- DWORD 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 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)
- {
- Write_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 failed.");
- 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);
- pFieldContent[TEST_CASE_MAX_FILE_LEN -1] = '/0';
-
- fclose(pFile);
-
- printf("The file %s content is: /n%s/n", szFileName, pFieldContent);
- Write_Log(LOG_TYPE_INFO, "The file %s content is: /n%s/n", szFileName, pFieldContent);
- }
- /*********************************************************************
- * 函數名稱:void Write_Log(unsigned int uiLogType, char *pstrFmt, ...)
- * 說明:日志寫函數,支持變長參數
- * 調用者:任何需要寫日志的地方
- * 輸入參數:
- * unsigned iType -- 日志類別
- * char *pstrFmt -- 日志內容
- * ... -- 變長參數
- * 輸出參數:
- * 無
- * 返回值:
- * void --
- * 作者: 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(&data, 0, sizeof(LOG_DATA));
- va_start(v1, pstrFmt);
- _vsnprintf(data.strText, MAX_LOGTEXT_LEN, pstrFmt, v1);
- va_end(v1);
- data.iType = uiLogType;
- curTime = time(NULL);
- mt = localtime(&curTime);
- strftime(data.strDate, sizeof(data.strDate), "%Y-%m-%d", mt);
- strftime(data.strTime, sizeof(data.strTime), "%H:%M:%S", mt);
- Write_Log_Text(&data);
- #endif _LOG_WRITE_STATE_
- }
- /*********************************************************************
- * 函數名稱:int GetLogPath(char *pStrPath)
- * 說明:獲取日志文件路徑
- * 調用者:Write_Log_Text
- * 輸入參數:
- * 無
- * 輸出參數:
- * char *pStrPath
- * 返回值:
- * int -- LOG_FAILED: 失敗
- * -- 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(&curTime);
- /* 根據日期組成文件夾名稱*/
- sprintf(pStrPath, "%s//%d%02d%02d", g_LogRootPath, mt->tm_year + 1900,
- mt->tm_mon + 1, mt->tm_mday);
- iRet = Create_LogDir(pStrPath);
- return iRet;
- }
- /*********************************************************************
- * 函數名稱:int GetLogFileName(int iLogType, const char *pStrPath, char *pStrName)
- * 說明:獲取日志文件名
- * 調用者:Write_Log_Text
- * 輸入參數:
- * int iLogType -- 日志類型 3種:INFO(0)/ERROR(1)/SYSTEM(2)
- * const char *pStrPath -- 日志路徑 由GetLogPath得到
- * 輸出參數:
- * char *pStrName -- 日志文件名
- * 返回值:
- * int -- LOG_FAILED: 失敗
- * -- LOG_SUCCESS: 成功
- * 作者: duanyongxing
- * 時間 : 2009-10-11
- *********************************************************************/
- int GetLogFileName(int iLogType, const char *pStrPath, char *pStrName)
- {
- if(NULL == pStrPath)
- {
- return LOG_FAILED;
- }
- char szLogName[MAX_FILE_PATH];
- FILE *pFile = NULL;
- memset(szLogName, 0, MAX_FILE_PATH);
- switch (iLogType)
- {
- case LOG_TYPE_INFO:
- sprintf(szLogName, "%s//app_info", pStrPath);
- break;
- case LOG_TYPE_ERROR:
- sprintf(szLogName, "%s//app_error", pStrPath);
- break;
- case LOG_TYPE_SYSTEM:
- sprintf(szLogName, "%s//app_system", pStrPath);
- break;
- default:
- return LOG_FAILED;
- break;
- }
- strcat(szLogName, ".log");
- if(IsFileExist(szLogName))
- {
- /* 如果文件長度大於指定的最大長度,重新創建一文件,覆蓋原文件*/
- if((int)GetFileLenth(szLogName) + 256 >= MAX_LOG_FILE_SIZE)
- {
- Create_LogFile(szLogName, 0);
- }
- }
- else
- {
- Create_LogFile(szLogName, 0);
- }
-
- sprintf(pStrName, "%s", szLogName);
- return LOG_SUCCESS;
- }
- /*********************************************************************
- * 函數名稱:int Create_LogDir(const char *pStrPath)
- * 說明:創建日志存放路徑
- * 調用者:GetLogPath
- * 輸入參數:
- * const char *pStrPath --用戶指定的根路徑
- * 輸出參數:
- * 無
- * 返回值:
- * int -- LOG_FAILED: 失敗
- * -- LOG_SUCCESS: 成功
- * 作者: duanyongxing
- * 時間 : 2009-10-11
- *********************************************************************/
- int Create_LogDir(const char *pStrPath)
- {
- if(NULL == pStrPath)
- {
- return LOG_FAILED;
- }
- int iRet = 0;
- char szSub[MAX_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(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;
- }
- else
- {
- if (!bFind)
- {
- bFind = 1;
- }
- else
- {
- memset(szSub, 0, sizeof(szSub));
- strncpy(szSub, pStrPath, 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: 失敗
- * -- LOG_SUCCESS: 成功
- * 作者: duanyongxing
- * 時間 : 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_NULL == 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
- * 時間 : 2009-10-11
- *********************************************************************/
- int 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 LOG_BOOL_FALSE;
- }
- }
- FindClose(hd);
- return LOG_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(&buff, 0, sizeof(WIN32_FIND_DATA));
- hd = FindFirstFile(pFile, &buff);
- FindClose(hd);
- return (buff.nFileSizeHigh * MAXDWORD) + buff.nFileSizeLow;
- }
- /*********************************************************************
- * 函數名稱:int Write_Log_Text(LPLOG_DATA lpLogData)
- * 說明:寫日志內容
- * 調用者:Write_Log
- * 輸入參數:
- * LPLOG_DATA lpLogData --日志內容結構體量
- * 輸出參數:
- * 無
- * 返回值:
- * int -- LOG_FAILED: 失敗
- * -- LOG_SUCCESS: 成功
- * 作者: duanyongxing
- * 時間 : 2009-10-11
- *********************************************************************/
- int Write_Log_Text(LPLOG_DATA lpLogData)
- {
- char szFilePath[MAX_FILE_PATH];
- char szFileName[MAX_LOG_FILE_NAME_LEN];
- FILE *pFile = NULL;
- char szLogText[MAX_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 %s/n", lpLogData->strDate, lpLogData->strTime,
- lpLogData->strText);
- fwrite(szLogText, 1, strlen(szLogText), pFile);
- fclose(pFile);
- return LOG_SUCCESS;
- }
Copyright ©
Linux教程網 All Rights Reserved