C++ 如何重定向 qDebug、qWarning、qCritical 等输出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4954140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to redirect qDebug, qWarning, qCritical etc output?
提问by Septagram
I'm using a lot of qDebug() <<
statements for debug output. Is there any cross-platform way I can redirect that debug output to a file, without resorting to shell scripts? I'm guessing that open()and dup2()will do the job in Linux, but will it work compiled with MinGW in Windows?
我在qDebug() <<
调试输出中使用了很多语句。是否有任何跨平台的方式可以将调试输出重定向到文件,而无需求助于 shell 脚本?我猜open()和dup2()可以在 Linux 中完成这项工作,但它可以在 Windows 中使用 MinGW 编译吗?
And maybe there is a Qt way to do it?
也许有一种 Qt 方法可以做到这一点?
回答by Nawaz
You've to install a message handler using qInstallMsgHandler
function, and then, you can use QTextStream
to write the debugmessage to a file. Here is a sample example:
您必须使用qInstallMsgHandler
函数安装消息处理程序,然后,您可以使用QTextStream
将调试消息写入文件。这是一个示例示例:
#include <QtGlobal>
#include <stdio.h>
#include <stdlib.h>
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
}
int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageOutput); // Install the handler
QApplication app(argc, argv);
...
return app.exec();
}
Taken from the doc of qInstallMsgHandler
(I only added the comments):
取自qInstallMsgHandler
(我只添加了评论)的文档:
In the above example, the function myMessageOutput
uses stderr
which you might want to replace with some other file stream, or completely re-write the function!
在上面的例子中,功能myMessageOutput
用途stderr
,你可能要与其他一些文件流更换或完全重新编写的功能!
Once you write and install this function, all your qDebug
(as well as qWarning
, qCritical
etc) messages would be redirected to the file you're writing to in the handler.
一旦你写并安装此功能,您所有的qDebug
(以及qWarning
,qCritical
等),消息将在处理程序被重定向到文件,您写信。
回答by Autodidact
From hereall credit goes to spirit.
#include <QApplication>
#include <QtDebug>
#include <QFile>
#include <QTextStream>
void myMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & msg)
{
QString txt;
switch (type) {
case QtDebugMsg:
txt = QString("Debug: %1").arg(msg);
break;
case QtWarningMsg:
txt = QString("Warning: %1").arg(msg);
break;
case QtCriticalMsg:
txt = QString("Critical: %1").arg(msg);
break;
case QtFatalMsg:
txt = QString("Fatal: %1").arg(msg);
break;
}
QFile outFile("log");
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << txt << endl;
}
int main( int argc, char * argv[] )
{
QApplication app( argc, argv );
qInstallMessageHandler(myMessageHandler);
...
return app.exec();
}
回答by Andrew
Here is a working example of hooking the default message handler.
这是挂钩默认消息处理程序的工作示例。
Thank you @Ross Rogers!
谢谢@罗斯罗杰斯!
// -- main.cpp
// Get the default Qt message handler.
static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = qInstallMessageHandler(0);
void myCustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
// Handle the messages!
// Call the default handler.
(*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg);
}
int main(int argc, char *argv[])
{
qInstallMessageHandler(myCustomMessageHandler);
QApplication a(argc, argv);
qDebug() << "Wello Horld!";
return 0;
}
回答by Neurotransmitter
Here is a cross-platform solution to log to the console, if the app was ran from the Qt Creator and to the debug.log
file, when it is compiled and being ran as a standalone app.
如果应用程序是从 Qt Creator 运行并登录到debug.log
文件,则当它被编译并作为独立应用程序运行时,这是一个登录到控制台的跨平台解决方案。
main.cpp:
主.cpp:
#include <QApplication>
#include <QtGlobal>
#include <QtDebug>
#include <QTextStream>
#include <QTextCodec>
#include <QLocale>
#include <QTime>
#include <QFile>
const QString logFilePath = "debug.log";
bool logToFile = false;
void customMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QHash<QtMsgType, QString> msgLevelHash({{QtDebugMsg, "Debug"}, {QtInfoMsg, "Info"}, {QtWarningMsg, "Warning"}, {QtCriticalMsg, "Critical"}, {QtFatalMsg, "Fatal"}});
QByteArray localMsg = msg.toLocal8Bit();
QTime time = QTime::currentTime();
QString formattedTime = time.toString("hh:mm:ss.zzz");
QByteArray formattedTimeMsg = formattedTime.toLocal8Bit();
QString logLevelName = msgLevelHash[type];
QByteArray logLevelMsg = logLevelName.toLocal8Bit();
if (logToFile) {
QString txt = QString("%1 %2: %3 (%4)").arg(formattedTime, logLevelName, msg, context.file);
QFile outFile(logFilePath);
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << txt << endl;
outFile.close();
} else {
fprintf(stderr, "%s %s: %s (%s:%u, %s)\n", formattedTimeMsg.constData(), logLevelMsg.constData(), localMsg.constData(), context.file, context.line, context.function);
fflush(stderr);
}
if (type == QtFatalMsg)
abort();
}
int main(int argc, char *argv[])
{
QByteArray envVar = qgetenv("QTDIR"); // check if the app is ran in Qt Creator
if (envVar.isEmpty())
logToFile = true;
qInstallMessageHandler(customMessageOutput); // custom message handler for debugging
QApplication a(argc, argv);
// ...and the rest of 'main' follows
Log formatting is handled by QString("%1 %2: %3 (%4)").arg...
(for the file) and fprintf(stderr, "%s %s: %s (%s:%u, %s)\n"...
(for console).
日志格式由QString("%1 %2: %3 (%4)").arg...
(对于文件)和fprintf(stderr, "%s %s: %s (%s:%u, %s)\n"...
(对于控制台)处理。
Inspiration: https://gist.github.com/polovik/10714049.
回答by Piotr Dobrogost
Well, I would say that the moment when you need to redirect your debug output to anything different than stderr is when you could think about some logging tool. If you feel you need one I would recommend using QxtLogger
("The QxtLogger class is an easy to use, easy to extend logging tool.") from Qxt
library.
好吧,我想说的是,当您需要将调试输出重定向到与 stderr 不同的任何内容时,您可以考虑使用某些日志记录工具。如果您觉得需要,我建议您使用库中的QxtLogger
(“QxtLogger 类是一种易于使用、易于扩展的日志记录工具。”)Qxt
。