参考帖子:https://blog.csdn.net/qq_43913513/article/details/130181874?spm=1001.2101.3001.6650.11&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-11-130181874-blog-134466662.235%5Ev40%5Epc_relevant_anti_t3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-11-130181874-blog-134466662.235%5Ev40%5Epc_relevant_anti_t3&utm_relevant_index=16
前言:
日志重定向输出类:QT5:qInstallMessageHandler QT4:qInstallMsgHandler
如果工程比较大,且确定好使用环境的话可以使用Log4Cpp;
TraceLog:cpp
#include "TraceLog.h"
#include <QFile>
TraceLog::TraceLog(QObject* parent)
: QObject{ parent }
{
}
TraceLog::~TraceLog()
{
qDebug("内存已释放");
}
//安装日志函数
void TraceLog::install()
{
// 安装消息处理函数 设置
// qInstallMessageHandler(outPutMsg);
// 创建log文件夹 应用所在文件下新建log文件夹
QString logPath = QApplication::applicationDirPath() + "/log";
QDir dir(logPath);
if (!dir.exists())
{
dir.mkdir(logPath);
qDebug() << "文件夹创建成功";
}
// deleteLog(); //删除过期日志
}
//卸载日志函数
void TraceLog::uninstall()
{
}
//日志信息处理函数
void TraceLog::outPutMsg(QtMsgType msgType, const QString& msg)
{
bool switchValue = false; //判断开关标志
static QMutex mutex; //设置互斥锁
//判断信息类型
QString type;
switch (msgType) {
case QtDebugMsg:
type = QString("Debug");
switchValue = true; //警告信息不能通过开关关闭
break;
case QtWarningMsg:
type = QString("Warning");
switchValue = true; //警告信息不能通过开关关闭
break;
case QtCriticalMsg:
type = QString("Critical");
switchValue = true; //危险信息不能通过开关关闭
break;
case QtFatalMsg:
type = QString("Fatal");
switchValue = true; //致命信息不能通过开关关闭
break;
case QtInfoMsg:
type = QString("Info");
default:
break;
}
if (switchValue == true) //判断配置开关是否打开
{
mutex.lock(); //互斥关锁
//文件名和行数以及函数
// QString contextInfo = QString("[File:(%1), Line:(%2), Funtion(%3)]:").arg(context.file).arg(context.line).arg(context.function);
//获取当前时间,精确到秒
QString currentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
//拼接信息字符串
QString message = QString("[%1] %2: %3").arg(currentTime).arg(type).arg(msg);
//存入信息到日志文件
saveLog(message, type);
mutex.unlock(); //开锁
}
}
//判断配置是否存在
bool TraceLog::judgeSwitch(QString switchName)
{
QSettings ini_config("logSetting.ini", QSettings::IniFormat);
ini_config.beginGroup("class_Switch");
bool isContains = ini_config.contains(switchName);
ini_config.endGroup();
return isContains;
}
//读取配置文件
QVariant TraceLog::read_ini_file(QString switchName)
{
QSettings ini_config("logSetting.ini", QSettings::IniFormat); // 创建QSettings 的对象
ini_config.beginGroup("class_Switch");
QVariant switchValue = ini_config.value(switchName);
ini_config.endGroup();
return switchValue;
}
//写入配置文件
void TraceLog::write_ini_file(QString switchName)
{
QSettings ini_config("logSetting.ini", QSettings::IniFormat);
ini_config.beginGroup("class_Switch");
ini_config.setValue(switchName, false);
ini_config.endGroup();
}
//删除过期日志
void TraceLog::deleteLog()
{
//获取日志文件夹地址
QString dirName = QApplication::applicationDirPath() + "/log";
QDir dir(dirName);
//获取文件夹下所有文件信息列表
QFileInfoList infoList = dir.entryInfoList(QDir::Files);
//遍历日志文件
foreach(QFileInfo fileInfo, infoList) {
//将文件创建时间与过期时间作比较,如果创建时间小于过期时间,则删除(代码是一分钟期限,如果改天为单位可以使用adddays)
if (fileInfo.birthTime() <= QDateTime::currentDateTime().addSecs(-1))
{
QFile::setPermissions(dirName + "/" + fileInfo.fileName(), QFileDevice::ReadOther | QFileDevice::WriteOther);
if (QFile::remove(dirName + "/" + fileInfo.fileName()))
{
qDebug("日志删除成功!");
}
else
{
qDebug("日志删除失败!");
}
}
}
}
//保存日志到文件
void TraceLog::saveLog(QString message, QString type)
{
int i = 1; //当文件大小超过最大值时,给新文件添加编号
//以天为单位给文件命名
QString fileName = QApplication::applicationDirPath() + "/log/" + QDateTime::currentDateTime().toString("yyyy-MM-dd") + "_" + type + "_log";
//文件名右边(后缀)
QString fileNameRight;
//最终要写入的文件名
QString fileNameLast = fileName + ".txt";
//绑定文件对象
QFile file(fileNameLast);
//判断文件大小
while (file.size() >= LOG_MAXSIZE)
{
//给新文件加入序号后缀
fileNameRight = QString("%1.txt").arg(i);
//拼接最终文件名
fileNameLast = fileName + fileNameRight;
//修改file绑定的文件名
file.setFileName(fileNameLast);
i++;
}
//只写和拼接的方式打开文件
bool isopen = file.open(QIODevice::WriteOnly | QIODevice::Append);
if (isopen == true)
{
QTextStream write(&file);
qDebug() << message;
write << message << "\r\n";
file.flush();
file.close();
}
}
TraceLog:h
#pragma once
#ifndef LOGOUTPUT_H
#define LOGOUTPUT_H
#include <QObject>
#include <QtMessageHandler>
#include <QDebug>
#include <QtDebug>
#include <QTextStream>
#include <QApplication>
#include <QDateTime>
#include <QMutex>
#include <QFile>
#include <QFileInfo>
#include <QMetaEnum>
#include <QSettings>
#include <QDir>
#define LOG_MAXSIZE 5 * 1024 // 单个log文件最大值
class TraceLog : public QObject
{
Q_OBJECT
public:
explicit TraceLog(QObject* parent = nullptr);
~TraceLog();
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
static void logThread::outPutMsg(QtMsgType type, const char* msg);
#else
//信息处理函数(重写的myMessageHandler)
/*功能说明:通过调试信息保存到日志文件
*
*参数说明:
* msgType: 调试信息类型或级别(qdebug, qwarning, qfatal 。。。。)
* context: 调试信息所处文本,可使用context.file和context.line获取文本所处行数及所处文件路径,以及使用context.function获取文本所处函数名
* msg: 调试信息内容,自定义
*/
static void outPutMsg(QtMsgType msgType, const QString& msg);
#endif
static void install(); // 安装信息处理函数
static void uninstall(); // 卸载信息处理函数
static void deleteLog(); // 删除过期日志
private:
/*
* 函数功能:
* 1、根据调试信息以及日期,保存到相应的文件。
* 2、在保存文件前需要判断文件大小是否大于自定义值,如果大于,便按照序号从小到大新建一个。
*
*
*/
static void saveLog(QString message, QString type);
// 参数为模块开关名
static bool judgeSwitch(QString switchName); // 判断模块是否存在
static void write_ini_file(QString switchName); //写入ini信息
static QVariant read_ini_file(QString switchName); // 读取ini信息
};
#endif // LOGOUTPUT_H
QtWidgetsApplication1.cpp
TraceLog traceLog;
QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this); // ui文件相关的代码
// 关联信号和槽
connect(this, SIGNAL(mySignal()), this, SLOT(mySlot()));
connect(this, SIGNAL(mySignal1(int)), this, SLOT(mySlot1(int)));
traceLog.install(); // 初始化日志 正常不应该在构造函数里初始化,我使用比较简单,大工程不建议写到这里
}
// 定义按钮触发的槽函数
void QtWidgetsApplication1::on_pushButton_clicked() {
traceLog.outPutMsg(QtDebugMsg, "QtWidgetsApplication1::on_pushButton_clicked invoke begin.");
slotFileNew();
traceLog.outPutMsg(QtDebugMsg, "QtWidgetsApplication1::on_pushButton_clicked invoke end.");
}
效果:
我只是用来记录小测试工具的操作日志,所以日志设置的比较简单。