持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
前言
之前一直是写纯C++程序的,MFC搭界面。程序中打印日志的方式,是通过创建一个日志类,在需要打印日志的地方,调用日志类的写入方法,将日志写到log.txt文件中,实现日志的记录功能。C++的代码实现起来还是比较繁琐的。
现在写Qt程序,Qt自己封装了很多功能,所以实现输出日志文件是比较方便的。它主要有两种方式:
第一种就是和纯C++输入日志的方法一样,自定义一个日志类,在程序想要输出日志的位置通过文件写入方式,按照指定的形式打印输出指定的内容。这种方法是需要我们手动完成的。
第二种是安装自定义的Qt消息处理程序,自动输出程序产生的调试消息、警告、关键和致命错误消息的函数。这种方法的好处是,你不需要在同一个地方既输出调试信息,又要输出日志信息。它可以直接将调试信息写入到日志文件中作为日志信息。
安装Qt消息处理程序 qInstallMessageHandler
qInstallMessageHandler介绍
qInstallMessageHandler(QtMessageHandlerhandler):
- 消息处理程序是一个输出调试消息、警告、关键和致命错误消息的函数。
- Qt库(调试模式)包含数百条警告消息,当发生内部错误(通常是无效函数参数)时,会打印这些警告消息。
- 在发布模式中内置的Qt也包含此类警告,除非在编译期间设置了QT_NO_WARNING_OUTPUT和/或QT_NO_DEBUG_OUTPUT。如果实现自己的消息处理程序,则可以完全控制这些消息。
- 默认消息处理程序将消息打印到X11下的标准输出或Windows下的调试器。如果是致命消息,应用程序立即终止。
- 只能定义一个消息处理程序,因为这通常是在应用程序范围内完成的,以控制调试输出。
日志功能实现
1.首先自定义消息处理函数
void LogMsgOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
// 加锁
QMutex mutex;
mutex.lock();
// 时间
QString strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
// 根据消息类型设置输出信息格式
QByteArray localMsg = msg.toLocal8Bit();
QString log;
switch (type) {
case QtDebugMsg:
log.append(QString("[%1] Debug Content: %2").arg(strTime).arg(msg));
break;
case QtInfoMsg:
log.append(QString("[%1] Info: %2").arg(strTime).arg(msg));
break;
case QtWarningMsg:
log.append(QString("Warning: %1 %2 %3 %4").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function));
break;
case QtCriticalMsg:
log.append(QString("Critical: %1 %2 %3 %4").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function));
break;
case QtFatalMsg:
log.append(QString("Fatal: %1 %2 %3 %4").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function));
abort();
}
// 创建日志文件并用时间信息命名
QFile file;
QString path = QCoreApplication::applicationDirPath() + QString("/Log/%1.log").arg(strTime);
file.setFileName(path);
// 输出信息至文件中(读写、追加形式)
if (!file.open(QIODevice::ReadWrite | QIODevice::Append))
{
QString erinfo = file.errorString();
}
else
{
QTextStream outStream(&file);
outStream << log << "\n\r";
file.flush();
file.close();
}
// 解锁
mutex.unlock();
}
2.然后调用qInstallMessageHandler安装该函数
// 在main函数中安装该函数。
int main(int argc, char *argv[])
{
bWriteLog = true;
if(bWriteLog)
{
qInstallMessageHandler(LogMsgOutput);
}
}
这样你在程序中所有调用qDebug、qInfo、qWarning、qCritical、qFatal的地方,都会打印到日志文件中。
通过bWriteLog标志位来设置是否输出日志信息。
3.消息类型讲解 QtMsgType这个枚举描述可以发送到消息处理程序(QtMessageHandler)的消息。可以使用枚举来标识各种消息类型,并将它们与适当的操作关联起来。
- QtDebugMsg:由qDebug()函数生成的消息。
- QtInfoMsg:由qInfo()函数生成的消息。
- QtCriticalMsg:由qCritical()函数生成的消息。
- QtFatalMsg:由qFatal()函数生成的消息。