zoukankan      html  css  js  c++  java
  • 简单的分级别写日志程序

    /************************************************************************/ 
    /*
      * 文件名称: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; 

    摘自 Socrates的专栏

  • 相关阅读:
    django--模型层(orm)-查询补充及cookie
    django-模型层(model)-多表相关操作(图书管理练习)
    Linux-正则表达式与三剑客
    网络配置命令优先级和元字符
    Linux-Nginx和NFS
    Linux-内存进程和软件安装
    乌龟棋
    倍增 Tarjan 求LCA
    切蛋糕
    HDU1505 City Game/玉蟾宫/全0子矩阵 悬线法
  • 原文地址:https://www.cnblogs.com/lizs/p/3718851.html
Copyright © 2011-2022 走看看