简单日志文件

/**********************************************************************
* 版权所有 (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语句,笨方法。

原文地址:https://www.cnblogs.com/shuqingstudy/p/5516603.html