C++打印日志功能设计
2016-04-14 19:20
357 查看
我之前用Qt框架下,设计了一个“打印日志”的功能(点击打开链接),利用了Qt框架的一些机制,并调用了一些的Qt框架函数。现在,我需要编写一个纯C++的“日志打印”功能。(事实上,还是调用了一些windows系统函数)
一、日志打印函数
我设计的是一个全局函数,而不是一个全局变量来实现log文件管理和输出。全局变量会导致“不可重入”,在多线程环境下,会概率性打印出错。
1, 事实上,我用的是类的static函数,增加了封装性,防止名称冲突。也可以用namespace来封装。
2,如果在多线程下,还可以在该函数中加“互斥锁”。
二、日志打印宏
在之前的Qt实现中,log文件不但包含时间,也包含文件名和行号。其实在纯C++中,也可实现该功能。具体来说,就是利用C++的编译宏“__FUNCTION__”、“__LINE__”、“__FILE__”和“__TIME__”(它显示的是编译时时间)等。如果要打印这些信息,它们就不能放到“PrintLog”这个全局函数中,而是要放到调用的地方,那么,解决的办法就是用“宏”。
1,对于分行的宏,最好用do-while包裹,比如调用的地方用的for循环,而没有加花括符。
2,在此选用的是C++的“字符流”,它能够识别字符串和其他类型变量,扩展性很好。
三、应用举例
打印结果如下:
四、文件管理
对于日志文件,一般有两种处理方式,一种就是每次启动软件,清空之前的文件;另一种就是累增。前一种的缺点是,长跑测试中,软件崩溃,后来者不小心重启了软件,导致历史日志丢失;后一种的缺陷是,长跑测试,日志文件累增过大,导致磁盘空间不足。
针对上面两种情况的优缺点,我设计了一种循环记录的方法,类似“行车记录仪”。
将该段代码加载程序启动的位置即可。
一、日志打印函数
我设计的是一个全局函数,而不是一个全局变量来实现log文件管理和输出。全局变量会导致“不可重入”,在多线程环境下,会概率性打印出错。
void CCommon::PrintLog(string str) { SYSTEMTIME sys; ::GetLocalTime(&sys); std::ofstream ofs; ofs.open("driver.log", std::ios_base::in | std::ios_base::app); ofs << "[" << sys.wHour << ":" << sys.wMinute << ":" << sys.wSecond << "." << sys.wMilliseconds << "]\t" << str << std::endl; ofs.close(); }
1, 事实上,我用的是类的static函数,增加了封装性,防止名称冲突。也可以用namespace来封装。
2,如果在多线程下,还可以在该函数中加“互斥锁”。
二、日志打印宏
在之前的Qt实现中,log文件不但包含时间,也包含文件名和行号。其实在纯C++中,也可实现该功能。具体来说,就是利用C++的编译宏“__FUNCTION__”、“__LINE__”、“__FILE__”和“__TIME__”(它显示的是编译时时间)等。如果要打印这些信息,它们就不能放到“PrintLog”这个全局函数中,而是要放到调用的地方,那么,解决的办法就是用“宏”。
#define PRINT_LOG(ss) \ do { \ std::ostringstream oss; \ oss << "Function: " << __FUNCTION__ << "\t\tMsg: " << ss; \ CCommon::PrintLog(oss.str()); \ } while(0);
1,对于分行的宏,最好用do-while包裹,比如调用的地方用的for循环,而没有加花括符。
2,在此选用的是C++的“字符流”,它能够识别字符串和其他类型变量,扩展性很好。
三、应用举例
double db = 5; std::ostringstream oss; oss << "Function: " << __FUNCTION__ << "\t\tMsg: " << db; CCommon::PrintLog(oss.str()); for (int i = 0; i < 20; ++i) PRINT_LOG("test" << 10);打印宏的括号内支持表达式,使用方法与C++标准流相同。
打印结果如下:
四、文件管理
对于日志文件,一般有两种处理方式,一种就是每次启动软件,清空之前的文件;另一种就是累增。前一种的缺点是,长跑测试中,软件崩溃,后来者不小心重启了软件,导致历史日志丢失;后一种的缺陷是,长跑测试,日志文件累增过大,导致磁盘空间不足。
针对上面两种情况的优缺点,我设计了一种循环记录的方法,类似“行车记录仪”。
long fileSize = 0; HANDLE handle = CreateFile(L"driver.log", FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (handle != INVALID_HANDLE_VALUE) { fileSize = GetFileSize(handle, NULL); cout << fileSize << endl; CloseHandle(handle); } if (fileSize < 200 * 1024 * 1024) // filesize的单位是byte,设定门限是200M { PRINT_LOG("\n\n------------------------------reboot----------------------------------"); } else DeleteFile(L"driver.log");
将该段代码加载程序启动的位置即可。
相关文章推荐
- C++基本语法-----template
- 逆置/反转单链表(C语言)
- 单链表实现约瑟夫环(JosephCircle)(C语言)
- 在无头单链表的一个非头节点前插入一个节点(C语言)
- c语言前n项求和如何实现?2个方法可行的
- 上周末没事写了一个UDP的例子 大家感兴趣的可以参考一下
- VC 自己封装简单的播放音频MCI类库
- iOS陆哥开发笔记(二十四) (C语言之内存四区和函数调用模型)
- C++11 标准新特性: 右值引用与转移语义
- 深搜-n皇后问题 1019
- 浅谈C++中的几种构造函数
- c++中的异常处理定义和使用方法
- 巩固C语言(三)----系统随机数 & 将文件写到指定文件夹
- Windows平台 C++遍历文件夹
- C++整理——const指针
- 腾讯2016春季校园实习招聘技术岗终面(HR面)问题汇总(CC++后台)
- 腾讯2016春季校园实习招聘技术岗终面(HR面)问题汇总(CC++后台)
- 用C语言输入密码
- [hihoCoder 1150] 基站选址(几何题,中心点)
- C语言strcasecmp