C语言Log输出收藏(转)

在网上找了好多自己写的轮子,最终还是非常喜欢这一款。

很简洁,基本功能也都可以满足。

原作者的文章http://blog.csdn.net/dyx1024/article/details/4720484

因为我在Unicode编译的,因此,作者的代码可能有些地方需要修改一下。

另外,根据自身的需要,对输出位置等下哦功能做了一点修改。


//
//Descript: common definition and function.
//  Author: guowemyan
//    Date:2013.12.17
//

#ifndef __WRITELOG_H__   
#define __WRITELOG_H__   


#include <string>
#include <iostream>

#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)   /* 测试函数中文件内容最大长度*/   



#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)  


void Write_Log(unsigned int uiLogType, char *pstrFmt, ...);  


#endif //__WRITELOG_H__   

/* 
* 文件名称:write_log.cpp 
* 摘    要:此文件实现了普通WINDOWS程序中的日志功能 
*           主要有以下特点: 
*           1. 根据日期创建日志文件目录,每天的日志分别存放在不同的日志目录中; 
*           2. 日志内容分三种类型,根据不同需要,写不同的日志类型的日志文件, 
*              方便通过日志定位、分析问题; 
*           3. 函数经过比较好的封装,便于复用; 
*           待改进点: 
*           1. 为了方便,日志内容打印时使用了time函数,其精确度较低; 
*           2. 可将这些函数封装为一个日志类,或者动态库,使其更通用; 
*           3. 没有考虑跨平台情景,目前只使用于WINDOWS下 
*           4. 日志文件内容还可进一步改进,比如打印出当前文件名与行号,使用日志功能 
*              更加实用; 
* 
* 当前版本:1.0 
* 作    者:duanyongxing  
* 完成日期:2009年10月11日 
*/                                                                       
/************************************************************************/  

#include "stdafx.h"   
#include <time.h>   
#include <memory.h>   
#include <stdio.h>   
#include <stdlib.h>    
#include <stdarg.h>   
#include <windows.h>   

#include "log.h"

const char g_LogRootPath[] = "C://My_APPLOG"; /*日志文件根路径,由用户指定*/  

const char g_LogLevelStr[][10] = {"INFO  ", "ERROR ", "SYSTEM"};


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 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);  
	sprintf(szLogName, "%s//TestParser", pStrPath); 
	/*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 = (char *)strchr(pStrPath + iLen, '//');  
		if(NULL == pSub)  
		{  
			if(iLen == 0)  
			{  
				return LOG_FAILED;  
			}  
			iRet = CreateDirectoryA(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);  
				CreateDirectoryA(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 = CreateFileA(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));  

	WCHAR szWcharStrFile[260] = _T("\0");
	MultiByteToWideChar(CP_ACP, 0, pStrFile, strlen(pStrFile), szWcharStrFile, sizeof(szWcharStrFile));

	HANDLE hd = FindFirstFile(szWcharStrFile, &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));  

	WCHAR szWcharFile[260] = _T("\0");
	MultiByteToWideChar(CP_ACP, 0, pFile, strlen(pFile), szWcharFile, sizeof(szWcharFile));

	hd = FindFirstFile(szWcharFile, &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 %s\n", g_LogLevelStr[lpLogData->iType], lpLogData->strDate, lpLogData->strTime, 
		lpLogData->strText);  
	fwrite(szLogText, 1, strlen(szLogText), pFile);  
	fclose(pFile);  
	return LOG_SUCCESS;  
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值