日志

日志文件应具备基本功能 Log4j据说是最闻名的日志文件类库,有针对于C++或者.NET的移植版本。一直不明白日志文件有什么特殊之处,也没有研究其功能强大在何处。 1. 理想中的日志文件类库功能应该具备:一个中心、两项基本功能、三个补充要求! 2. 一个中心点: 使用简单就是使用的时候可以感觉日志功能是随插随用,不用在代码层次上做太多前期的步骤。 3. 两个基本功能:日志类型管理、日志文件管理 日志类型管理包括:格式化输出、日期时间标记等。前者可以考虑为日志分类,后者带上时间标记便于跟踪调试分析。 日志文件管理包括:日志文件的大小约定、按时间段整理等 4. 三点补充要求:多种类型信息输出、多个进程输出到同一个日志文件、多进程线程同时输出时互斥操作 以下是根据在实际过程中的运用,封装一个简单的日志文件功能模块。麻雀虽小,但是却满足以上所有要求。其中,对于日志文件管理这块简单点约定输出到指定文件名。由于采用CString,因此仅适用于MFC!但是可以方便的改造为纯C|C++。 //=============================================================== // LOG::简单的日志工具 // 日志功能包应该包括以下两块功能: // 1. 每个日志文本串 // 目前日志文本串包括 [prefix][datetime][type][info...] // a.多个进程输出到同一个日志文件,可通过prefix来区分每个进程; 可以忽略 // b.datetime可以用来测试时间 // c.类型可以设定[error|warn|debug], // 由使用者任意使用,并不做明确标记; 也可以忽略 // d.info,可以根据实际情况任意格式化输出,类似printf // 2. 日志文件 // a. 可将日志串保存到文本,或者自己处理 // b. 支持并发写操作 // c. 日志文件的管理 //=============================================================== ________________________________________ .h文件 class LOG { public: LOG(); virtual ~LOG(); public: //-日志文件- //----如果没有指定,则为exe所在路径下的log.log文件---- static CString GetLogFile(); static short SetLogFile(LPCTSTR strPath); static short ViewLogFile(); //-前缀- //----如果多个进程往同一个文件输出日志,可以为每个进程设置一个前缀---- //----前缀出现在日期时间之前---- static short SetPrefix(LPCTSTR strPrefix); //-日志信息- //-获取日志字符串,可以另外- static CString sOutV(LPCTSTR strType, LPCTSTR strFormat = NULL, va_list valist = NULL); static CString sOut0(LPCTSTR strType, LPCTSTR strFormat = NULL,...); static CString sOut ( LPCTSTR strFormat = NULL,...); //-将日志信息输出到文件- static short OutV(LPCTSTR strType, LPCTSTR strFormat = NULL, va_list valist = NULL); static short Out0(LPCTSTR strType, LPCTSTR strFormat = NULL,...); static short Out (LPCTSTR strFormat = NULL,...); protected: static CString s_strLogFile; static CString s_strLogPrefix; static HANDLE s_hWriteEvent; }; ________________________________________ .cpp文件 // 得到可执行程序所在目录 // BOOL bIncludeSep -- 是否包含最后的分隔符"/" CString GetExePath(BOOL bIncludeSep) { // 得到当前的文件名 CString strFileName; GetModuleFileName(AfxGetInstanceHandle(),strFileName.GetBuffer(_MAX_PATH),_MAX_PATH); strFileName.ReleaseBuffer(); // 得到当前目录 strFileName=strFileName.Left(strFileName.ReverseFind(_T('//'))+1); if(bIncludeSep) return strFileName; else return strFileName.Left(strFileName.GetLength()-1); } //-获取最后的文件名 如果给定文件不是全路径,就是相对于exe- CString GetFileForExePath(LPCTSTR strCurFileName) { CString strPath = strCurFileName; if(!strPath.IsEmpty()) { //-相对路径- if(strPath.Find(_T(":"))<=0) { strPath.Format(_T("%s%s"), GetExePath(FALSE), strCurFileName); } } return strPath; } #define LOG_EVENT _T("ChyLogWrite") CString LOG::s_strLogFile = _T(""); CString LOG::s_strLogPrefix = _T(""); HANDLE LOG::s_hWriteEvent = NULL; LOG::LOG() { } LOG::~LOG() { } short LOG::SetLogFile(LPCTSTR strPath) { if(strPath==NULL || strPath[0]==0) s_strLogFile = GetFileForExePath("log.log"); else s_strLogFile = GetFileForExePath(strPath); return 1; } CString LOG::GetLogFile() { return s_strLogFile; } short LOG::ViewLogFile() { CString strLogFile = GetLogFile(); ShellExecute(NULL, _T("open"), strLogFile, NULL, NULL, SW_SHOW); return strLogFile.IsEmpty()?0:1; } short LOG::SetPrefix(LPCTSTR strPrefix) { if(strPrefix && strPrefix[0]) { s_strLogPrefix = strPrefix; } return 1; } CString LOG::sOutV(LPCTSTR strType, LPCTSTR strFormat, va_list valist) { CString strPart_Prefix; if(!s_strLogPrefix.IsEmpty()) { strPart_Prefix.Format(_T("[%s]"), s_strLogPrefix); } CString strPart_Time; { SYSTEMTIME sysTime = {0}; GetLocalTime(&sysTime); strPart_Time.Format(_T("[%2d-%2d %2d:%2d:%2d_%3d]"), sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds); } CString strPart_Type; if(strType && strType[0]) { strPart_Type.Format(_T("[%s]"), strType); } CString strPart_Info; { strPart_Info.FormatV(strFormat, valist); } CString str = strPart_Prefix + strPart_Time + strPart_Type+ strPart_Info; return str; } CString LOG::sOut0(LPCTSTR strType, LPCTSTR strFormat,...) { va_list valist; va_start(valist, strFormat); CString strInfo = sOutV(strType, strFormat, valist); va_end(valist); return strInfo; } CString LOG::sOut(LPCTSTR strFormat,...) { va_list valist; va_start(valist, strFormat); CString strInfo = sOutV(NULL, strFormat, valist); va_end(valist); return strInfo; } short LOG::OutV(LPCTSTR strType, LPCTSTR strFormat, va_list valist) { //-- if(s_hWriteEvent==NULL) { s_hWriteEvent = OpenEvent(0, FALSE,LOG_EVENT); if(s_hWriteEvent==NULL) s_hWriteEvent = CreateEvent(NULL, FALSE, TRUE, LOG_EVENT); } WaitForSingleObject(s_hWriteEvent, INFINITE); //-打开关闭文件- if(s_strLogFile.IsEmpty()) SetLogFile(NULL); CStdioFile file; if(file.Open(s_strLogFile, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite)) { CString strPart_NewLine = _T("/n"); CString strInfo = sOutV(strType, strFormat, valist); CString str = strPart_NewLine + strInfo; file.SeekToEnd(); file.WriteString(str); file.Close(); } SetEvent(s_hWriteEvent); return 1; } short LOG::Out0(LPCTSTR strType, LPCTSTR strFormat,...) { va_list valist; va_start(valist, strFormat); short rtn = OutV(strType, strFormat, valist); va_end(valist); return rtn; } short LOG::Out(LPCTSTR strFormat,...) { va_list valist; va_start(valist, strFormat); short rtn = OutV(NULL, strFormat, valist); va_end(valist); return rtn; } ________________________________________ 使用说明 //-设定日志文件,建议在Exe初始化时设定- //-设置相对路径则表示exe所在路径下- //-如果不设定则为exe所在路径下的log.log文件- LOG::SetLogFile("bbb.log"); //-获取日志文本串,可以自行处理,例如输出到界面- CString str; str = LOG::sOut0("debug", "hello"); str = LOG::sOut0("warn5", "hello %d", 25); str = LOG::sOut0("warn3", "hello %s, you have %d apples!", "libai", 10); str = LOG::sOut ("hello %s, you have %d apples!", "libai", 10); //-输出到文件- LOG::Out0("debug", "hello"); LOG::Out0("warn5", "hello %d", 25); LOG::Out0("warn3", "hello %s, you have %d apples!", "libai", 10); LOG::Out ("hello %s, you have %d apples!", "libai", 10); //-查看日志文件- LOG::ViewLogFile(); ________________________________________ 输出效果 [ 7-28 17:23:59_ 31][debug]hello [ 7-28 17:24: 0_ 93][warn5]hello 25 [ 7-28 17:24: 0_343][warn3]hello libai, you have 10 apples! [ 7-28 17:24: 0_593]hello libai, you have 10 apples!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值