Qt 日志 QDebug 输出至文件

版权声明:未经许可,请勿转载! https://blog.csdn.net/weixin_37204973/article/details/82530713

        程序员每天必做的事情就是写 bug,那么调试信息就是必不可少的,网上博文大多是讲如何将调试信息保存至本地,但有时候我想记录到本地,并打印至ui 界面,或者其它地方,网上却没有很好的博文去介绍这个怎么做,所以只能想办法了,自己做了。

首先是调试消息处理的类

//MyDebug.cpp

#include "MyDebug.h"
#include <QMutex>
#include <iostream>
#include <QDateTime>
#include <QCoreApplication>
#include <QFile>
#include <QDir>
#include <QTextStream>

//接收调试信息的函数
void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    static QMutex mutex;
    QMutexLocker lock(&mutex);

    QString text;
    switch(type)
    {
    //如果是debug信息,那么直接打印至应用程序输出,然后退出本函数
    case QtDebugMsg:
        std::cout << msg.toStdString() << std::endl;
        return ;

        //如果是警告,或者是以下消息,则继续执行后面的数据处理
    case QtWarningMsg:
        text = QString("Warning...............................");
        break;

    case QtCriticalMsg:
        text = QString("Critical..............................");
        break;

    case QtFatalMsg:
        text = QString("Fatal.................................");
        break;

    default:
        text = QString("Default...............................");
        break;
    }
    //获取单例
    MyDebug *instance = MyDebug::Instance();
    //消息输出位置
    QString context_info = QString("File: %1\r\nFunc: %2\r\nLine: %3")
            .arg(QString(context.file))
            .arg(QString(context.function))
            .arg(context.line);
    //消息打印时间
    QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");    
    QString current_date = QString("Time: %1")
            .arg(current_date_time);
    //调试信息
    QString message = QString("%1\r\n%2\r\n%3\r\n%4")
            .arg(text)
            .arg(current_date)
            .arg(context_info)
            .arg("MSG : "+msg);
    //log 位置
    QString logPahtHtml = "<a href = \"%1\">Click here to open the log directory.</a>\r\n";
    logPahtHtml = logPahtHtml.arg(QCoreApplication::applicationDirPath()+"/"+instance->logPath());
    //将调试信息格式化成 html 格式,
    QString msgHtml = msg;
    msgHtml.replace("  ", "&nbsp;");
    msgHtml.remove("\r");
    msgHtml.replace("\n", "<br>");
    msgHtml = QString("<font color=red>" + msgHtml + "</font>");

    QString contextInfoHtml = context_info;
    contextInfoHtml.remove("\r");
    contextInfoHtml.replace("\n", "<br>");
    //格式化后的调试信息
    QString messageHtml = QString("%1<br>%2<br>%3<br>%4<br>%5")
            .arg(text)
            .arg(logPahtHtml)
            .arg(current_date)
            .arg(contextInfoHtml)
            .arg("MSG : "+msgHtml);

    //将调试信息写入文件
    QFile file(instance->logPath() + instance->logName());
    file.open(QIODevice::WriteOnly | QIODevice::Append);
    QTextStream text_stream(&file);
    text_stream << message << "\r\n\r\n\r\n";
    file.flush();
    file.close();
    //将处理好的调试信息发送出去
    instance->sigDebugStrData(message);
    //将处理成 html 的调试信息发送出去
    instance->sigDebugHtmlData(messageHtml);    
    //检查文件是否达到了指定大小
    if(file.size() < 1024*1024) {
        return ;
    }
    //log达到了限制值则将名字更改,防止文件越来越大
    for(int loop = 1; loop < 100; ++loop) {
        QString fileName = QString("%1/log_%2.txt").arg(instance->logPath()).arg(loop);
        QFile file_1(fileName);
        if(file_1.size() < 4) {
            file.rename(fileName);
            return ;
        }
    }
}

//MyDebug单例
MyDebug* MyDebug::self = nullptr;
MyDebug* MyDebug::Instance()
{
    if(!self) {
        QMutex muter;
        QMutexLocker clocker(&muter);

        if(!self) {
            self = new MyDebug();
        }
    }
    return self;
}
//安装消息器
void MyDebug::installMessageHandler()
{
    qInstallMessageHandler(outputMessage);
}
//卸载消息器
void MyDebug::uninstallMessageHandler()
{
    qInstallMessageHandler(0);
}
//建立文件路径
QString MyDebug::logPath()
{
    QString current_date_file_name = QDateTime::currentDateTime().toString("yyyy-MM-dd");
    QDir dir(QString("log/%1").arg(current_date_file_name));
    if(!dir.exists()) {
        dir.mkpath("./");
    }
    return dir.path() + "/" ;
}

QString MyDebug::logName()
{
    return "log.txt";
}

MyDebug::MyDebug(QObject *parent) : QObject(parent)
{    
    static MyDebug::GC gc;
}

MyDebug::~MyDebug()
{
    std::cout << "~MyDebug" << std::endl;
}

//垃圾自动回收
MyDebug::GC::~GC()
{
    if (self != nullptr) {
        delete self;
        self = nullptr;
    }
}

类做完了,使用前需要先安装消息器

//main.cpp
#include "mainwindow.h"
#include <QApplication>
#include "MyDebug.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //安装消息器
    MyDebug::Instance()->installMessageHandler();

    MainWindow w;
    w.show();

    return a.exec();
}

如果需要打印调试信息至ui ,那么使用下面这两个信号即可,可以说是很方便了

    void sigDebugStrData(const QString &);
    void sigDebugHtmlData(const QString &);

//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "MyDebug.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //绑定信号,将调试信息输出值ui
    connect(MyDebug::Instance(), &MyDebug::sigDebugHtmlData, ui->textBrowser, &QTextBrowser::append);
}

MainWindow::~MainWindow()
{    
    delete ui;    
}

void MainWindow::on_pushButton_clicked()
{
    qDebug()  << "这条消息只会打印至\"应用程序输出\"" <<endl;
    qWarning()<< "这条消息会记录至文件,并打印至ui"<<endl;
}

下图就是程序运行效果,点击绿色字体,就会将 log 所在位置的文件夹打开

这里写图片描述

源码地址

好啦,小弟拙作,如果不对的地方,欢迎大神们批评指正!

猜你喜欢

转载自blog.csdn.net/weixin_37204973/article/details/82530713