前言:在各个大佬的文章里面逛了逛,并没有看到适合的通用的日志打印模式,这就想着自己写一个出来,就有了这篇文章
(还有待更新中)
1.目的:
(1)能够选择性打印日志到应用程序输出窗口、text文本窗口、文件输出等
(2)有不通的日志类型
(3)能够打印出有效的十六进制数组
(4)采用宏、重载函数
(5)足够简单
2.分析:打印的最直接手段 Qstring 数据类型,不论是 qDebug() 函数的显示,还是ui->textEdit->setText() 函数的参数
3.首先第一个问题,日志打印需要多个描述,多个参数,参数多种形式输出,能够满足的,比较简单的是 printf 函数,但是这个只能输出到应用程序输出,不满足第(1)(5)两点,所以这里选择 sprintf 函数,定义一个能够全局使用的 Qstring 数据类型的数据流变量
xxx.c
QString debug_logStream;
xxx.h
extern QString debug_logStream;
4.使用宏+参数对该数据流进行重新定义,控制输出的方向。使用 qDebug() 对 debug_logStream 进行输出的时候,若使用 Qstring() 的时候会把 "" 双引号也打印出来,特别影响观感,所以得采用别的形式,去符号输出
#define __DEBUG_ON // 日志开关
#ifdef __DEBUG_ON
#define log_debug(isQdebug, format, ...) \
do{ \
debug_logStream.sprintf(format, ##__VA_ARGS__); \
if(isQdebug) \
{ \
qDebug().noquote()<<debug_logStream; \
} \
}while(0x00)
#else
#define log_debug(isQdebug, format, ...)
#endif
实际输出效果如下,控制输出流方向达到需要的效果
5.扩展日志的类型,根据严重类型,囊括错误/告警/日志的时间、文件名、行数、函数名等
#define log_fatal(isQdebug, format, ...) \
do{ \
log_debug(isQdebug, "-> [%s] Fatal @ File : %s Line : %d Func : %s \n" format "\n", \
__TIME__, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
}while(0x00)
#define log_warn(isQdebug, format, ...) \
do{ \
log_debug(isQdebug, "-> [%s] Warn @ Func : %s \n" format "\n", __TIME__, __func__, ##__VA_ARGS__); \
}while(0x00)
#define log_info(isQdebug, format, ...) \
do{ \
log_debug(isQdebug, "-> [%s] Info : " format "\n", __TIME__, ##__VA_ARGS__); \
}while(0x00)
实际效果,后续测试不输出到text文本框,统一使用应用程序输出口
其实,所有的所有到这里就可以结束了,但是总会有一些特殊的需求
6.打印十六进制数据,这里试过很多种方法,都不是很尽人意,比如最简单的 toHex() 函数,确实可以简单做到,但是又要做到每个数据需要用空格间隔开来,又要用到 replace(QRegularExpression("(..)"), "\\1 "); 函数,这样的话做不到数据流控制方向(也许单纯自己菜)
所以采用最古老的方式,自己写
/*
* @brief 十六进制数组显示
* @param uint8_t mod : 模式,0x01 : 显示在固定的调试窗口
* 0x00 : 可以作为显示在text文本框
* @param const char* info : 描述信息
* @param uint8_t* data : 数组
* @param uint16_t len : 需要显示的长度
* @return void
*/
void xxx::debug_logHex(uint8_t mod, const char *info, uint8_t *data, uint16_t len)
{
QByteArray tmp;
uint8_t date[0x10];
sprintf((char *)date, "[%s]", __TIME__);
// sprintf((char *)date, "[%s]", QTime::currentTime().toString("hh:mm:ss.zzz").toLatin1().data());
tmp.append((const char *)date, strlen((const char *)date));
if(info != NULL)
{
tmp.append(' ');
tmp.append((const char *)info);
}
tmp.append(" Hex = ", strlen("Hex = "));
tmp.append(' ');
for(uint16_t i = 0x00; i < len; i++)
{
tmp.append((data[i] >> 0x04) + (((data[i] >> 0x04) > 0x09) ? '7' : '0'));
tmp.append((data[i] & 0x0F) + (((data[i] & 0x0F) > 0x09) ? '7' : '0'));
tmp.append(' ');
}
tmp.append('\n');
log_debug(mod, "%s", tmp.data());
}
7.最后在相应的.h文件里面进行重载
public:
static QString debug_stream;
void debug_logHex(uint8_t mod, const char *info, uint8_t *data, uint16_t len);
void debug_logHex(const char *info, uint8_t *data, uint16_t len)
{
debug_logHex(0x01, info, data, len);
}
void debug_logHex(uint8_t mod, uint8_t *data, uint16_t len)
{
debug_logHex(mod, NULL, data, len);
}
void debug_logHex(uint8_t *data, uint16_t len)
{
debug_logHex(0x01, NULL, data, len);
}
效果如下
结:再想想有没有啥需要更新的,到时候再写