4.4 案例8 用qDebug()输出信息

article/2025/10/14 17:02:12

本案例对应的源代码目录:src/chapter04/ks04_04。

在开发C/S(Client/Server,客户端/服务端)模式的软件时,服务端程序(有时也称作服务)经常运行在两种模式下。

(1)终端模式。

终端模式,也可称作命令行模式。在这种模式下,服务端程序占用终端(命令行)运行,用户既可以看到服务端程序向终端输出的信息,也可以在终端输入命令以调整程序的行为。

(2)后台模式。

后台模式就是Windows的服务模式(在Linux、Unix下也有服务模式)。在这种模式下,服务端程序以后台服务方式运行,而且没有任何界面。用户无法通过终端查看模块状态或者输入命令,因为根本就没有终端。当软件运行在这种模式的时候,维护人员给服务器加电后就可以不管了,服务器加电启动后进入操作系统并且自动启动预先配置好的服务。因为这种模式几乎无须人员干预,所以对用户来说非常方便。

通常可以在软件中通过命令行参数的方式区分这两种模式。如果软件运行在终端模式,可以将输出信息发送到标准输出(也就是命令行);如果软件运行在后台模式,可以将输出信息保存到文件。那么该怎么实现这样的信息输出功能呢?

Qt提供了qDebug()来实现输出功能。下面分4种场景介绍qDebug()相关的功能。

(1)用qDebug()<<方式输出信息。

(2)使用qDebug(“%”)格式化输出信息。

(3)将自定义类输出到qDebug()。

(4)将标准输出重定向到文件。

下面进行详细介绍。

1.用qDebug()<< 方式输出信息

最简单的方法是直接向终端输出信息,方法是使用<<操作符实现信息输出,见代码清单4-22。

代码清单4-22

#include <QDebug>

void example01() {                      

    int iVal = 334;

    QString str = "I live in China";

    qDebug() << "My Value is " << iVal << ". " << str;

    qWarning() << "My Value is " << iVal << ". " << str;

    qCritical() << "My Value is " << iVal << ". " << str;

}

从代码清单4-22可以看出,使用<<操作符将变量输出到qDebug()的方法跟STL的cout类似,即把变量左移到qDebug()即可。Qt的常用类都可以输出到qDebug(),原生数据类型也是。qWarning()、qCritical()的用法与qDebug()相同,只是严重等级不同。使用时需要包含<QDebug>文件。

2.使用qDebug(“%”)格式化输出信息

为了便于信息的阅读,实际工作中运行的软件一般都采用格式化的方式输出信息,见代码清单4-23。

代码清单4-23

void example02(){                       

    QString str = "China";

    QDateTime dt = QDateTime::fromTime_t(time(NULL));

    qDebug("I live in %s. Today is %04d-%02d-%02d", str.toLocal8Bit().data(), dt.date().year(), dt.date().month(), dt.date().day());

    qWarning("I live in %s. Today is %04d-%02d-%02d", str.toLocal8Bit().data(),

    dt.date().year(), dt.date().month(), dt.date().day());

    qCritical("I live in %s. Today is %04d-%02d-%02d",

str.toLocal8Bit().data(), dt.date().year(), dt.date().month(), dt.date().day());

    // 下面几行代码如果解封,其功能是弹出异常界面,并显示给出的异常信息。

    // qFatal("I live in %s. Today is %04d-%02d-%02d",                       

    //         str.toLocal8Bit().data(),

    //         dt.date().year(), dt.date().month(), dt.date().day());

}

在代码清单4-23中,使用类似sprintf()的方式实现信息的格式化输出。代码中用%语法将信息格式化。qWarning()、qCritical()、qFatal()的用法与之相同。标号①处封掉的代码中,qFatal()正常运行的效果是弹出异常界面。

3.将自定义类输出到qDebug()

除了Qt自带的类之外,还可以将项目中的自定义类输出到qDebug(),如代码清单4-24所示。

代码清单4-24

// myclass.h

#pragma once

#include <QDebug>

#include <QString>

class CMyClass {

    ...

};

QDebug operator<<(QDebug debug, const CMyClass &mc);                                 

代码清单4-24提供了自定义类CMyClass的头文件。为了将自定义类输出到qDebug,在标号①处为CMyClass编写左移操作符的重载接口。该接口的实现见代码清单4-25。在代码清单4-25中的重载接口内部,根据实际需要将CMyClass类对象mc的数据输出到debug对象。

代码清单4-25

// myclass.cpp

#include "myclass.h"

QDebug operator<<(QDebug debug, const CMyClass &mc) {

    debug << "My id is " << mc.getId() << ", My Name is " << mc.getName() << "";

    return debug;

}

完成CMyClass类向qDebug()的左移操作符的重载操作后,就可以在代码中使用它了,见代码清单4-26中标号①处。

代码清单4-26

void example03(){

    CMyClass mc;

    mc.setId(10000);

    mc.setName(QString::fromLocal8Bit("秦始皇"));

    qDebug() << mc;                                                               

}

4.将标准输出重定向到文件

除了将信息输出到终端,还可以通过重定向的方式将信息输出到文件。当软件模块以服务模式运行在后台时,如果能把调试信息输出到文件中,就可以方便地监视软件运行状态。这将用到Qt的重定向输出接口的注册函数qInstallMessageHandler()。该函数的原型为:

Q_CORE_EXPORT QtMessageHandler qInstallMessageHandler(QtMessageHandler);

从qInstallMessageHandler()的定义可以看出,需要给它传入一个QtMessageHandler类型的新的重定向输出函数地址,然后它返回前一个(旧的)QtMessageHandler函数地址。QtMessageHandler定义如下。

typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &);

为了使用qInstallMessageHandler(),开发者需要定义自己的重定向接口customMessageHandler(),如代码清单4-27所示。

代码清单4-27

QMutex g_mutex; // 为了支持多线程功能,需要使用锁来保护对日志文件的操作。           ①

QtMessageHandler g_systemDefaultMessageHandler = NULL; // 用来保存系统默认的输出接口 ②

void customMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& info) {

    // 把信息格式化

    QString log =

    QString::fromLocal8Bit("msg-[%1], file-[%2], func-[%3], cate-[%4]\r\n").arg(info).arg(context.file).arg(context.function).arg(context.category);            

    bool bok = true;

    switch (type) {

    case QtDebugMsg:

        log.prepend("Qt dbg:");

        break;

    case QtWarningMsg:

        log.prepend("Qt warn:");

        break;

    case QtCriticalMsg:

        log.prepend("Qt critical:");

        break;

    case QtFatalMsg:

        log.prepend("Qt fatal:");

        break;

    case QtInfoMsg:

        log.prepend("Qt info:");

        break;

    default:

        bok = false;

        break;

    }

    if (bok) {

        // 加锁

        QMutexLocker locker(&g_mutex);                                         

        QString strFileName = getPath("$TRAINDEVHOME/bin/log04_04.inf");

        QFile file(strFileName);

        if (!file.open(QFile::ReadWrite | QFile::Append)) {

            return;

        }

        file.write(log.toLocal8Bit().data());

        file.close();

    }

    if (bok) {

        // 调用系统原来的函数完成信息输出,比如输出到调试窗口

        if(NULL != g_systemDefaultMessageHandler)    {                         

            g_systemDefaultMessageHandler(type, context, log);

        }

    }

}

// main.cpp

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

    QApplication app(argc, argv);

    // 输出重定向

    g_systemDefaultMessageHandler = qInstallMessageHandler(customMessageHandler); 

    ...

}

代码清单4-27中定义的customMessageHandler()接口提供3个参数。参数type用来区分报警等级,其取值见表4-2。参数context用来指示上下文,比如输出信息时所在文件、行号、所在函数等。参数info用来描述需要输出的信息内容。在代码清单4-27中的customMessageHandler()接口中,根据type的不同,对info进行了重新组织并将格式化后的信息存放到log中,最后将log写入日志文件。为了防止多线程对同一个日志文件的操作,在标号①处定义一个互斥对象g_mutex,并在标号③处通过QMutexLocker自动锁来操作g_mutex,以便对日志文件的操作进行互斥。QMutexLocker实现的功能是在构造QMutexLocker对象时可以对传入的g_mutex进行加锁处理,并在析构时对g_mutex进行解锁处理,这样就实现了加锁解锁的自动化操作,开发者无须关注加锁、解锁操作。为了调用系统原来的信息输出功能(比如将信息输出到调试窗口),可以先定义变量用来保存旧的信息输出接口,见标号②处、标号⑤处代码,然后在标号④处调用旧的信息输出接口将信息输出到调试窗口。在标号⑤处,main()函数中调用qInstallMessageHandler()来注册自定义的重定向输出接口customMessageHandler,这样当后续代码中调用qDebug()、qWarning()、qCritical()、qFatal()时程序就会自动调用自定义的customMessageHandler()接口来输出信息。请注意,在Release版本中有可能出现参数context对象中的文件信息和行数为空,原因是Qt在Release版本默认丢弃了文件信息、行数等信息。解决方案是在项目的pro文件中定义一个宏:

// ks04_04.pro

DEFINES += QT_MESSAGELOGCONTEXT

表4-2 QtMsgType取值

取值

说明

取值

说明

QtDebugMsg

调试类信息

QtFatalMsg

致命错误信息

QtWarningMsg

一般的警告信息

QtInfoMsg

一般的信息提示

QtCriticalMsg

严重错误信息

QtSystemMsg = QtCriticalMsg

系统信息 

----------------------------------------------------------------------------------------------------------------------------------------------

《Qt 5/PyQt 5实战指南》目录


http://chatgpt.dhexx.cn/article/5fxpAYSw.shtml

相关文章

Qt扫盲-QDebug理论总结

QDebug理论使用总结 一、概述二、使用1. 基础使用2. 格式化选项3.将自定义类型写入流 一、概述 每当开发人员需要将调试或跟踪信息写入设备、文件、字符串或控制台时&#xff0c;都会使用QDebug。这个就可以方便我们调试&#xff0c;基本上Qt所有的内容都能通过调试打印出来&a…

Qt重定向QDebug,自定义一个简易的日志管理类

0.前言 相对于第三方的日志库&#xff0c;在 Qt 中使用 QDebug 打印更便捷&#xff0c;有时候也需要对 QDebug 输出进行重定向&#xff0c;如写入文件等。 在 Qt4 中使用 qInstallMsgHandler 函数设置重定向的函数指针&#xff1a; typedef void (*QtMsgHandler)(QtMsgType,…

qDebug 控制台输出

做个小笔记:qDebug 控制台输出 Ⅰ&#xff1a;*.pro文件中添加 win32:CONFIG console Ⅱ&#xff1a;配置项目运行设置&#xff0c;将Run in terminal 复选框打勾 Ⅲ&#xff1a;添加头文件 #include <QDebug> Ⅳ&#xff1a;用qDebug()<<"xxxx";输…

Qt ——debug调试

程序调试&#xff1a; 方法一&#xff1a;断点调试法方法二&#xff1a;使用qDebug()函数 方法一&#xff1a;断点调试法 我们可以在程序加断点&#xff0c;然后再利用单步调试查看变量的值是否异常。 1. 设置断点。 可以左击相应的代码行前的区域&#xff08;下图用红色框标…

jadx反编译—下载和使用(傻瓜教程,非常详细)

原文地址 一、在GitHub上直接下载 下载地址 可以下这个版本&#xff1a; 二、运行图形化界面 1、将zip文件解压后定位到在lib文件夹中&#xff0c;在此处打开命令行 2、运行jadx-gui-0.7.1.jar&#xff08;前提是已经装好了JDK1.8&#xff09; 命令如下&#xff1a; <sp…

Android APK 反编译工具 JADX

文章目录 JADX 介绍JADX 安装JADX 使用补充APK 目录结构含义APK 打包流程 JADX 介绍 GitHub 地址&#xff1a;https://github.com/skylot/jadx JADX 支持将 APK, dex, aar, zip 中的 dalvik 字节码反编译为 Java 代码&#xff0c;也支持反编译 AndroidManifest.xml 和 resource…

jadx-gui 重命名功能

jad-gui 是大家常用的一款反编译工具&#xff0c;其中有些小使用技巧可以帮助大家更快的“学习”知识。 安装 方法参考项目GitHub主页 重命名 最新的 1.2.0 版本支持了方法、类、字段的重命名&#xff0c;这是一个非常有用的功能&#xff0c;之前反编译出来的都是混淆后的名…

Android 反编译神器jadx的使用

一、前言 今天介绍一个非常好用的反编译的工具 jadx 。jadx 的功能非常的强大&#xff0c;对我而言&#xff0c;基本上满足日常反编译需求。 jadx 优点&#xff1a; 图形化的界面。拖拽式的操作。反编译输出 Java 代码。导出 Gradle 工程。 这些优点都让 jadx 成为我反编译…

jadx工具windows下载

Release v1.2.0 skylot/jadx GitHubDex to Java decompiler. Contribute to skylot/jadx development by creating an account on GitHub.https://github.com/skylot/jadx/releases/tag/v1.2.0选择第三个jadx-gui-1.2.0-with-jre-win.zip解压exe可正常使用

jadx反编译—下载和使用

一、在GitHub上直接下载 https://github.com/skylot/jadx 可以下这个版本&#xff1a; 二、运行图形化界面 1、将zip文件解压后定位到在lib文件夹中&#xff0c;在此处打开命令行 2、运行jadx-gui-0.7.1.jar&#xff08;前提是已经装好了JDK1.8&#xff09; 命令如下&#xf…

jadx初识

一.jadx介绍 一款相对流行的反编译工具 下载&#xff1a;https://github.com/skylot/jadx/releases/tag/v1.0.0 解压后得到这么几个文件&#xff1a; 启动&#xff1a;&#xff08;以下来两个文件都可以&#xff09; 启动后的界面&#xff1a; 二.使用 打开之后&#xff0c;你可…

反编译工具之jadx

反编译神器之 - jadx git网址&#xff1a; https://github.com/skylot/jadx简介 首先推荐功能强大的jadx&#xff0c;官方网站为&#xff1a;https://github.com/skylot/jadx&#xff0c;可以直接在releases页面下载其最新版&#xff0c;解压即可使用。 安装 Windows下安装 …

Android 反编译工具 jadx-gui

jadx-gui 是一种基于 jadx 项目的图形界面工具&#xff0c;用于反编译 Android 应用程序的工具。通过使用jadx-gui&#xff0c;开发人员可以打开 APK&#xff08;Android应用程序包&#xff09;文件&#xff0c;并查看其反编译的源代码。这对于分析、理解和调试 Android 应用程…

jadx工具介绍及使用

往期推荐 签名校验之“xx银行” Jeb调试ctf(破解密码 Crack the key) ”川报观察“协议分析(抓不到包) 实战分析43XX的HTTPS协议 需要相关资料的朋友&#xff0c;可以【加入此处即可打包获取】 jadx工具是一款反编译利器&#xff0c;同时支持命令行和图形界面&#xff0c…

Java jar反编译工具 jadx

jadx 支持 Windows、Linux、 macOS 项目下载地址 https://github.com/skylot/jadx/releases 按需下载 1.下载zip解压后&#xff0c;进入 bin 目录即可找到执行脚本 jadx&#xff1a;命令行版本 jadx-gui&#xff1a;图形操作界面版本2.下载exe本地双击运行&#xff0c;将…

kali Linux 逆向环境pyenv、Frida、objection、jadx、的安装

目录 1.pyenv安装和使用 1.1pyenv 简介 1.2pyenv 常用命令 1.3pyenv安装和使用 2.Frida安装 2.1Fraida简介 2.1Fraida安装 2.2objection安装 2.3objection常用命令 查看日志 查看包含Frida的日志信息 查看objection的帮助命令 2.3.0进入objection REPL环境 2.3.1直接…

jadx动态调试安卓apk

选用某ctf题目的apk作为调试目标。 工具&#xff1a; 雷电模拟器 jadx1.3.2 步骤&#xff1a; 1、在雷电模拟器安装apk&#xff1a; 2、在jadx打开apk&#xff1a; 3、检查模拟器的adb服务状态&#xff1a; 必须确保模拟器里的adb服务启动&#xff0c;且状态正常&#xff0…

android 反编译 jadx,jadx gui下载 jadx(Android反编译gui工具) v0.6.1 官方版 下载-脚本之家...

jadx是一款Android反编译gui工具&#xff0c;它支持apk、dex、jar、class、zip、aar等文件。jadx操作方便&#xff0c;反编译后的代码可读性高&#xff0c;同时还拥有较完善的gui界面&#xff0c;除去混淆部分的代码&#xff0c;jadx已经非常接近源代码了。需要的朋友可以下载试…

jadx反编译

刚发现的一个反编译神器jadx,对比之前的apktool跟dex2jar,jadx胜在可读性好太多,apktool后的smali长的跟汇编语言一样,dex2jar产生的源码也经常出现奇奇怪怪的语法,让我理解不能. jadx GitHub 地址:https://github.com/skylot/jadx 下载或克隆后,在目录下运行 ./gradlew dis…

新版jadx-gui导入dex会提示Bad checksum

新版jadx-gui导入dex会提示Bad checksum 问题解决方案 问题 今天将一个app脱壳后&#xff0c;拿到DEX&#xff0c;导入jadx中时&#xff0c;弹出了一个错误 也就是会校验dex的checksum&#xff0c;此时如果关闭按钮&#xff0c;忽略错误&#xff0c;会导致dex文件反编译失败&…