• 简单日志文件


    /**********************************************************************
    * 版权所有 (C)2015, 王茂春。
    *
    * 文件名称:WriteLog.c
    * 文件标识:无
    * 内容摘要:演示日志信息的打印方法
    * 其它说明:无
    第一,本文中对日志信息的写入采用的是直接在日志文件后面追加的方式,因此每次测试之前,要在“log”目录下删除上一次产生的“WriteLog.log”文件,
          否则新的日志信息会写入旧的日志文件中。 
    第二,由于写日志函数WriteLogFile的入参较多,每次调用的时候编写代码较为繁琐,因此使用一个宏WRITELOGFILE来代替,且只需要带上日志等级和日志消息两个参数即可,
          其它的如代码文件名、函数名和代码行数直接使用系统自定义的宏即可。
    * 完成日期:20160522
    *
    **********************************************************************/
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    #include <sys/time.h>
    
    // 函数宏定义
    #define WriteLogFile(level, msg)  writeLog((char *)__FILE__, (char *)__FUNCTION__, __LINE__, level, (char *)msg)
    
    // 全局变量
    typedef char INT8;
    INT8    LogFileName[100] = "WriteLog.log";  // 带路径的日志文件名
    
    // 函数声明
    void writeLog(char *pFileName,char *pFunctionName,int iCodeLine,int iLogLevel,char *pContent);
    void GetTime(char *pszTimeStr);
    /**********************************************************************
     * 功能描述: 获取时间串
     * 输入参数: pszTimeStr-时间串
     * 输出参数: pszTimeStr-时间串
     * 返 回 值: 无
     * 其它说明: 时间串样式: YYYY.MM.DD HH:MIN:SS.Usec
     * 修改日期        版本号         修改人         修改内容
     * -------------------------------------------------------------------
     * 2016年5月22日     V1.0        王茂春      创建
     ********************************************************************/ 
    void GetTime(char *pszTimeStr)
    {
        struct tm      tSysTime     = {0};
        struct timeval tTimeVal     = {0};
        time_t         tCurrentTime = {0};
    
        INT8  szUsec[20] = {0};    // 微秒
        INT8  szMsec[20] = {0};    // 毫秒
    
        if (pszTimeStr == NULL)
        {
            return;
        }
    
        tCurrentTime = time(NULL);
        localtime_r(&tCurrentTime, &tSysTime);   // localtime_r是线程安全的
    
        gettimeofday(&tTimeVal, NULL);    
        sprintf(szUsec, "%06ld", tTimeVal.tv_usec);  // 获取微秒
        strncpy(szMsec, szUsec, 3);                // 微秒的前3位为毫秒(1毫秒=1000微秒)
    
        sprintf(pszTimeStr, "[%04d.%02d.%02d %02d:%02d:%02d.%3.3s]", 
                tSysTime.tm_year+1900, tSysTime.tm_mon+1, tSysTime.tm_mday,
                tSysTime.tm_hour, tSysTime.tm_min, tSysTime.tm_sec, szMsec);
    }
    
    
    /**********************************************************************
     * 功能描述: 将内容写到日志文件中
     * 输入参数: pFileName-代码文件名
                  pFunctionName-代码所在函数名
                  iCodeLine-代码行
                  iLogLevel-日志等级(0,1,2,3)
                  pContent-每条日志的具体内容
     * 输出参数: 无
     * 返 回 值: 无
     * 其它说明: 无
     * 修改日期        版本号         修改人          修改内容
     * -------------------------------------------------------------------
     * 20160522        V1.0           王茂春          创建 
     ********************************************************************/    
    void writeLog(char *pFileName,char *pFunctionName,int iCodeLine,int iLogLevel,char *pContent)
    {
     
      char  szTimeStr[128]     = {0};
      char  szLogContent[128]  = {0};
      FILE  *fp                = NULL;
      
    
      //判断文件名,函数名,日志文件名是否为空
      if (pFileName == NULL || pFunctionName == NULL || LogFileName == NULL )
      {
            printf("eer");
            return;
      }
      fp = fopen(LogFileName, "at+");      // 打开文件, 每次写入的时候在后面追加
      if (fp == NULL)
      {
         return;
      }
      // 先打印版本相关信息
      //snprintf(szLogContent, sizeof(szLogContent)-1, "/******Version [1.0], Build time[%s %s].****/
    ", __DATE__, __TIME__);
      //fputs(szLogContent, fp);
      // 写入日志时间
      GetTime(szTimeStr);
      fputs(szTimeStr, fp);
      //在日志信息中显示"文件名/函数名/代码行数"信息
      //0 === 严重错误
      if (0 == iLogLevel)
      {
        snprintf(szLogContent, sizeof(szLogContent)-1, "[%s][%s][%04d][%s]%s
    ", pFileName, pFunctionName, iCodeLine, "LOG_FATAL", pContent);
      }
      //1 === 一般错误
       if(1 == iLogLevel)
      {
        snprintf(szLogContent, sizeof(szLogContent)-1, "[%s][%s][%04d][%s]%s
    ", pFileName, pFunctionName, iCodeLine, "LOG_ERROR", pContent);
      }
      //2 === 警告
       if(2 == iLogLevel)
      {
        snprintf(szLogContent, sizeof(szLogContent)-1, "[%s][%s][%04d][%s]%s
    ", pFileName, pFunctionName, iCodeLine, "LOG_WARN", pContent);
      }
      //3 === 一般信息
       if(3 == iLogLevel)
      {
        snprintf(szLogContent, sizeof(szLogContent)-1, "[%s][%s][%04d][%s]%s
    ", pFileName, pFunctionName, iCodeLine, "LOG_INFO", pContent);
      }
    
      fputs(szLogContent, fp);
      fflush(fp);     // 刷新文件
      fclose(fp);     // 关闭文件
      fp = NULL;      // 将文件指针置为空
    
      return;
    }
    
    void test()
    {
    WriteLogFile(2,"hhh----fun");
    WriteLogFile(3,"hhh----fun");
    
    }
    int main()
    {
      
    WriteLogFile(0,"hhh----main");
    WriteLogFile(1,"hhh----main");
    test();
    }

    本文借鉴 周兆雄 博客,写一个自己的简单的日志文件。

    优点:

       1. 仅仅提供三个入口:日志文件名、错误等级、错误信息,其他(所属文件名,函数名,所在行,错误等级字符均隐藏)

      2. 使用了宏定义函数,简化函数操作

      3.文件操作使用snprintf比sprintf更优秀。

    缺点:

     1.文件采用无限追加模式,每次运行前需要删除日志

     2.原博客也是对“const char *"转换为”char ")经常错误出现,这里的解决办法使用强制转换,比如:

    writeLog((char *)__FILE__, (char *)__FUNCTION__, __LINE__, level, (char *)msg)

    3.本文为了简便起见,对错误等级使用if判断,而没有使用switch语句,笨方法。

  • 相关阅读:
    深入理解 IE haslayout
    electron的应用
    自动化批量录入Web系统
    Flask + Vue的一个示例
    如何从git仓库里下载单个文件夹
    Django项目设置首页
    简单更改Django Admin登录页面
    Flask web项目使用.flaskenv文件
    Flask 里url_for的使用
    使用Flask-migrate迁移数据库
  • 原文地址:https://www.cnblogs.com/shuqingstudy/p/5516603.html
Copyright © 2020-2023  润新知