`
javasogo
  • 浏览: 1816621 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

简单的分级别写日志程序

 
阅读更多

/************************************************************************/
/*
* 文件名称: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 intiType; /* 日志类型: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;

}

分享到:
评论

相关推荐

    C简单的分级别写日志程序归类.pdf

    这个PDF文件描述的是一个简单的C语言日志记录程序,用于在不同的级别(如信息、错误和系统)分类记录日志。日志功能在许多应用程序中都很重要,因为它可以帮助开发者追踪和调试程序的行为,特别是在处理复杂问题或...

    程序写日志代码, 简单, 实用。

    在编程领域,日志记录是不可或缺的一部分,它帮助开发者跟踪程序运行状态,定位错误和调试问题。本资源提供了一个简单的C++日志系统实现,包括`SysLog.cpp`和`SysLog.h`两个核心文件以及`使用说明.txt`,旨在为...

    简单的写日志的文件C++

    "简单的写日志的文件C++"这个项目,正如其名,提供了使用C++语言实现基础日志记录功能的方法。在C++中,没有内置的日志库,所以通常需要开发者自己实现或者使用第三方库来处理日志。 首先,我们需要了解日志的基本...

    应用log4net写日志的简单程序

    标题"应用log4net写日志的简单程序"表明我们要讨论的是如何使用log4net这个开源日志记录库在C#环境中编写日志处理代码。log4net是Apache的一个项目,广泛应用于.NET框架,提供了一种灵活、可配置的日志记录解决方案...

    c++写日志文件类

    本文将深入探讨如何使用C++编写一个简单但实用的日志文件类,以便在开发过程中记录和分析程序运行情况。 首先,让我们从`logfile.h`头文件开始。这个文件通常会定义我们的日志类`Logger`,它可能包含以下几个核心...

    linux程序中写日志的类实现

    在实际应用中,我们可以根据程序的需要设置日志级别,只记录特定级别的错误。例如,在生产环境中,可能只记录ERROR和WARN级别的日志,而在开发和调试阶段,可以开启DEBUG级别的日志以获取更多信息。 此外,为了提高...

    c++写日志dll,三种方式单一、每日、固定大小

    在给定的标题“c++写日志dll,三种方式单一、每日、固定大小”中,我们可以理解为这是关于如何使用C++编写一个动态链接库(DLL)来实现不同类型的日志记录策略:单一文件、每日滚动和固定大小的日志文件。...

    C语言写日志函数

    标题中的“C语言写日志函数”指的是创建一个用C语言编写的函数,该函数负责将日志信息写入指定的日志文件中。描述中提到的输入参数`pPath`代表日志文件的完整路径,而`pLogText`则表示要写入日志的具体内容。 下面...

    一个简单的写日志的类

    - **日志级别**:添加枚举类型来表示不同的日志级别(如DEBUG、INFO、WARNING、ERROR),使得日志记录可以根据需要过滤特定级别的信息。 - **时间戳**:在写入日志时自动添加当前时间戳,方便追踪事件发生的时间。 -...

    c# 写日志小工具类

    本文将深入探讨“c# 写日志小工具类”的核心概念、实现方式以及它在实际开发中的应用。 日志记录通常包括记录错误、警告、信息和调试消息,这些记录可以帮助我们在程序出现问题时进行诊断。一个简单的日志小工具类...

    C# 高效安全写日志源码、调用示例

    让我们深入探讨一下这个"高效安全写日志源码"的核心知识点。 1. **多线程安全**: 在多线程环境中,多个线程可能同时尝试写入日志文件,如果不加以控制,可能会导致数据冲突和文件损坏。这个源码通过引入锁(Mutex...

    android--java写日志文件

    总之,正确地使用Java在Android中写日志是优化应用质量和提升开发效率的重要手段。理解不同日志级别,遵循良好的日志编写习惯,并根据需要扩展日志功能,将有助于在开发过程中快速定位和解决问题。

    读写日志文件

    在IT行业中,日志文件是记录应用程序运行状态、错误信息以及调试信息的重要工具。日志系统可以帮助开发者追踪软件的问题,优化性能,以及确保系统的稳定运行。本文将详细讲解如何编写一个支持多线程读写日志的程序。...

    MFC 写日志文件

    在IT行业中,日志文件是调试、监控和问题排查的重要工具。MFC(Microsoft Foundation Classes)...在实际开发中,你还可以考虑添加更复杂的功能,比如日志级别控制、日志滚动、多线程安全性等,以满足不同项目的需求。

    C++ 写日志函数

    在IT行业中,日志记录是软件开发不可或缺的一部分,它能够帮助开发者追踪程序运行的状态,定位错误,以及进行性能分析。本文将深入探讨如何使用C++编写一个简单的日志功能,并结合给定的"3.cpp"文件,理解其实现原理...

    Qml写日志QmlLog4Qml.7z

    QmlLog4Qml是一个专为Qt Quick(Qml)设计的日志记录工具,它使得在Qml应用程序中实现日志记录变得简单高效。在Qml编程中,日志记录对于调试、性能分析以及问题排查至关重要。QmlLog4Qml提供了一套完整的API,允许...

    java写一个日志程序

    在实际应用中,日志程序可能需要更复杂的功能,如日志级别控制(debug、info、warn、error)、日志切割(按日期或大小分割日志文件)、日志归档以及使用专门的日志框架如Log4j或SLF4J等。这些高级特性可以帮助我们更...

    自己写的日志库

    标题提到的“自己写的日志库”是一个自定义的日志处理库,旨在提供一种简单易用的方式来记录应用程序的日志信息。描述中提到的“使用简单方便”意味着这个库设计时注重了用户体验,让开发者能够快速集成并有效地利用...

    C#写日志文件

    在.NET开发环境中,日志记录是一项非常重要的任务,它帮助开发者追踪程序运行状态,调试错误,以及维护系统稳定性。C#作为.NET Framework的主要编程语言,提供了多种方式来实现日志功能,其中log4net是一个广泛使用...

    VB编写日志记录,简单的

    本主题将详细介绍如何使用VB来编写简单的日志记录功能,特别是结合ListView控件实现这一功能。 日志记录通常涉及以下几个步骤: 1. **创建日志文件**:在VB中,我们可以通过`My.Computer.FileSystem.WriteAllText`...

Global site tag (gtag.js) - Google Analytics