当前位置: 移动技术网 > IT编程>开发语言>C/C++ > 简单的分级别写日志程序

简单的分级别写日志程序

2019年04月19日  | 移动技术网IT编程  | 我要评论
/************************************************************************/ 
/*
  * 文件名称: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的专栏

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网