Qt5的Log打印

转载 2018年04月16日 15:20:26

背景:

一般情况下,我们调试版本会在code里面添加一些qDebug来帮助我们修改代码。

但是当我们的软件版本发布出去,用户告诉我们软件使用出问题了,并且我们在自己的实验室无法复现问题怎么办?

这个时候怎么依靠我们之前在代码里面添加的qDebug呢?

只要用户动动小手,改个配置文件就会把原来代码里面的log输出到一个txt里,然后送给我们分析问题。

方法:

首先,我们使用帮助文档看下Qt5的这个方法

  1. QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)  
我们可以看到下面信息。

  1. #include <qapplication.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4.   
  5. void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)  
  6. {  
  7.     QByteArray localMsg = msg.toLocal8Bit();  
  8.     switch (type) {  
  9.     case QtDebugMsg:  
  10.         fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  11.         break;  
  12.     case QtInfoMsg:  
  13.         fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  14.         break;  
  15.     case QtWarningMsg:  
  16.         fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  17.         break;  
  18.     case QtCriticalMsg:  
  19.         fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  20.         break;  
  21.     case QtFatalMsg:  
  22.         fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);  
  23.         abort();  
  24.     }  
  25. }  
  26.   
  27. int main(int argc, char **argv)  
  28. {  
  29.     qInstallMessageHandler(myMessageOutput);  
  30.     QApplication app(argc, argv);  
  31.     ...  
  32.     return app.exec();  
  33. }  

显而易见,它给我们举了个例子,告诉我们怎么使用,并且也详细描述了。

The message handler is a function that prints out debug messages, warnings, critical and fatal error messages. The Qt library (debug mode) contains hundreds of warning messages that are printed when internal errors (usually invalid function arguments) occur. Qt built in release mode also contains such warnings unless QT_NO_WARNING_OUTPUT and/or QT_NO_DEBUG_OUTPUT have been set during compilation. If you implement your own message handler, you get total control of these messages.

我们只需要把他的信息保留到txt文件中就可以了。

同时在代码里面定义个宏,

  1. #ifndef QT_DEBUG  
  2.     installReleaseMsgHandler();  
  3. #endif  
Debug模式在QtCreater里面显示,Release模式编译输出文件流。

注意:

如果Release模式下,在软件运行输出日志到txt的时候,用户这时关闭软件,我们必须要有个关闭txt文件的操作。

这个时候你需要了解下 这个函数

  1. void qAddPostRoutine(QtCleanUpFunction ptr)  
Adds a global routine that will be called from the QCoreApplication destructor. This function is normally used to add cleanup routines for program-wide functionality.

以上基本就可以满足我们的要求了。

下来请赏脸看下我写的例子:

  1. #include <QApplication>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <QCoreApplication>  
  5. #include <QSettings>  
  6. #include <QDebug>  
  7. #include <QTime>  
  8. #include <QDir>  
  9.   
  10. #define _TIME_ qPrintable(QTime::currentTime().toString("hh:mm:ss:zzz"))  
  11.   
  12. static FILE *q_fileStream = NULL;  
  13. static int   g_logLevel   = 0;  
  14.   
  15. enum TraceLevel  
  16. {  
  17.     TL_NULL = 0,  
  18.     TL_CRIT,  
  19.     TL_ERRO,  
  20.     TL_WARN,  
  21.     TL_INFO  
  22. };  
  23.   
  24. static const int g_TraceLevel [] = { TL_INFO, TL_WARN, TL_ERRO, TL_CRIT, TL_NULL };  
  25.   
  26. static void SoftWareShutDown ()  
  27. {  
  28.     if (NULL != q_fileStream)  
  29.     {  
  30.         qDebug("Close log file.");  
  31.         fclose (q_fileStream);  
  32.         q_fileStream = NULL;  
  33.     }  
  34. }  
  35.   
  36. void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)  
  37. {  
  38.     Q_UNUSED(type);  
  39.     QByteArray localMsg = msg.toLocal8Bit();  
  40.     if (g_logLevel && q_fileStream)  
  41.     {  
  42.         int iLevel = g_TraceLevel[type];  
  43.         if (g_logLevel < iLevel)  
  44.         {  
  45.             return;  
  46.         }  
  47.   
  48.         fprintf (q_fileStream, "%s: %s (%s:%u, %s)\n", _TIME_, localMsg.constData(), context.file, context.line, context.function);  
  49.         fflush (q_fileStream);  
  50.     }  
  51. }  
  52.   
  53. static void installMsgHandler(QString strLogFile)  
  54. {  
  55.     QByteArray byteArrayLogFile = strLogFile.toLatin1();  
  56.   
  57.     if (NULL != q_fileStream)  
  58.     {  
  59.         fclose (q_fileStream);  
  60.         q_fileStream = NULL;  
  61.     }  
  62.   
  63.     q_fileStream = fopen (byteArrayLogFile.constData (), "w+");  
  64.     if (NULL != q_fileStream)  
  65.     {  
  66.         qDebug("Opened log file.");  
  67.         qInstallMessageHandler(myMessageOutput);  
  68.     }  
  69.     else  
  70.     {  
  71.         qDebug("Failed to open log file.");  
  72.     }  
  73. }  
  74.   
  75. static void installReleaseMsgHandler ()  
  76. {  
  77.     QString strAppPath = QCoreApplication::applicationDirPath();  
  78.     QString strIniFile = strAppPath + "/RunInfo.ini";  
  79.     QString strLogFile = strAppPath + "/log.txt";  
  80.     QSettings pSettings(strIniFile, QSettings::IniFormat);  
  81.     g_logLevel = pSettings.value("TraceSet/TraceLevel", 1).toInt();  
  82.     installMsgHandler (strLogFile);  
  83. }  
  84.   
  85. int main(int argc, char *argv[])  
  86. {  
  87.     QApplication a(argc, argv);  
  88. #ifndef QT_DEBUG  
  89.     bool bAddQuitFunc = false;  
  90.     installReleaseMsgHandler();  
  91.     if (!bAddQuitFunc)  
  92.     {  
  93.         qAddPostRoutine (SoftWareShutDown);  
  94.         bAddQuitFunc = true;  
  95.     }  
  96. #endif  
  97.     Window w;  
  98.     w.show();  
  99.     return a.exec();  
  100. }  

运行顺序:

1. 判断是否为Release

2. installReleaseMsgHandler     // 初始化 ini信息,和log文件位置

3. installMsgHandler                  // 打开文件,并调用 qInstallMessageHandler

4. myMessageOutput                // 根据之前 读取的log等级 按照要求输出log
5. qAddPostRoutine                  // 检测软件是否关闭,调用关闭文件函数

6. SoftWareShutDown              // 关闭文件


同时说明下,我的RunInfo.ini文件信息

就两行

[TraceSet]
TraceLevel=4

平时为1 ,当我们需要打log的时候改为4(全部信息,qDebug/qWarning/qCritical/qInfo),改为3的时候....自己试试吧。


上面代码的CSDN链接:http://download.csdn.net/detail/c3060911030/9464986

主要 ini文件要放置正确位置,在运行目录下。

J2EE vs. NET, Java vs. C#:比较公正的评价

J2EE vs. NET, Java vs. C#:Since theres been plenty of discussion on these topics, I thought Id write...
  • Nightmare
  • Nightmare
  • 2003-06-02 11:42:00
  • 1929

Qt5如何输出日志输出文件

  在Qt开发过程当中经常使用qDebug等一些输出来调试程序,但是到了正式发布的时候,都会被注释或者删除,采用日志输出来代替。做过项目的童鞋可能都使用过日志功能,以便有异常错误能够快速跟踪、定位,Q...
  • CLinuxF
  • CLinuxF
  • 2018-01-02 09:41:34
  • 265

qt5框架—打印功能的实现

qt是一款优秀的程序框架,使跨平台图形界面的开发容易很多,节省大量的工作量 。它既可以开发GUI程式,也可用于开发非GUI程式,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称...
  • qianmeiling2848
  • qianmeiling2848
  • 2016-05-10 20:58:25
  • 1487

Qt5 文本打印

打印的代码如下:void ImageProcessor::ShowPrintText() { QPrinter printer; QPrintDialog printDialog(&p...
  • xinweilaizhe
  • xinweilaizhe
  • 2014-08-14 17:08:12
  • 947

log4qt(Qt5下可以使用)qtlog记录

  • 2014年06月04日 11:13
  • 186KB
  • 下载

Qt5发布版本的日志输出

  • 2016年03月17日 23:09
  • 2KB
  • 下载

用QT 写的一个Log

#ifndef CLOG_H #define CLOG_H #include #include #include #include class CLog { priva...
  • du_bingbing
  • du_bingbing
  • 2016-07-01 14:58:56
  • 374

qt5 log

背景: 一般情况下,我们调试版本会在code里面添加一些qDebug来帮助我们修改代码。 但是当我们的软件版本发布出去,用户告诉我们软件使用出问题了,并且我们在自己的实验室无法复现问题...
  • ldw614
  • ldw614
  • 2017-11-17 10:09:16
  • 105

android打印log工具

  • 2018年01月31日 18:36
  • 362KB
  • 下载

Qt 调试信息,输出日志

注:以下方法仅适用于 Qt5 及以上版本 参考:Qt之qInstallMessageHandler(输出详细日志) Qt之qInstallMessageHandler(重定向至...
  • qq_35488967
  • qq_35488967
  • 2017-08-01 13:48:57
  • 723
收藏助手
不良信息举报
您举报文章:Qt5的Log打印
举报原因:
原因补充:

(最多只允许输入30个字)