Qt5實(shí)現(xiàn)qDebug日志信息寫入日志文件過程
1、思路
其實(shí)Qt提供了將日志寫入文件的方式,是以接口的形式提供的,我們只需要按照我們的需求完成回調(diào)函數(shù)和我們自己的接口即可。
為方便調(diào)用,我們一般直接寫到log.h中即可。
- 1、創(chuàng)建log.h
- 2、根據(jù)我們自己的需求完成回調(diào)函數(shù)
- 3、根據(jù)需求封裝外部調(diào)用函數(shù)并注冊(cè)回調(diào)函數(shù)
2、代碼
我這里按照我的需求,當(dāng)接口傳遞日志文件名和等級(jí)時(shí)使用傳遞的文件存儲(chǔ)日志,否則以精確到當(dāng)前時(shí)間為文件名創(chuàng)建日志文件。
提供給外部的調(diào)用函數(shù)包含日志文件名和日志等級(jí)兩個(gè)接口,可以不傳遞,直接使用默認(rèn)值。
Log.h
#ifndef LOG_H#define LOG_H#include <QFile>#include <QTextStream>#include <QDateTime>#include <QMutex>//選擇屏幕打印還是輸出到文件可以根據(jù)這個(gè)宏控制或者控制函數(shù)調(diào)用位置都可以//#define _DEBUG//默認(rèn)調(diào)試級(jí)別為warning,即小于warning級(jí)別的都不會(huì)寫入日志文件//只有release版本的時(shí)候,才會(huì)輸出到日志,debug版本正常輸出到終端。namespace QT_LOG{<!--{C}%3C!%2D%2D%20%2D%2D%3E--> //默認(rèn)文件名為當(dāng)前時(shí)間命名的log文件 static int m_LogLevel = 1; static QString m_LogFile = QString("%1.log").arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmss")); QMutex m_LogMutex; void customMessageHandler(QtMsgType type , const QMessageLogContext &context , const QString &msg) {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> //設(shè)置輸出日志級(jí)別,小于該級(jí)別,將不會(huì)寫入日志文件,默認(rèn)是warning級(jí)別,即debug信息不會(huì)寫入日志文件 if (type < m_LogLevel) {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> return; } QString log_info; switch (type) {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> case QtDebugMsg: log_info = QString("%1[Debug]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); break; case QtWarningMsg: log_info = QString("%1[Warning]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); break; case QtCriticalMsg: log_info = QString("%1[Critical]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); break; case QtFatalMsg: log_info = QString("%1[Fatal]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); abort(); case QtInfoMsg: log_info = QString("%1[Info]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); break; } log_info += QString(context.file) + QString(context.line) + QString("%1").arg(msg); //為了線程安全 m_LogMutex.lock(); QFile outFile(m_LogFile); outFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text); QTextStream ts(&outFile); ts << log_info << endl; outFile.close(); m_LogMutex.unlock(); } //默認(rèn)調(diào)試級(jí)別為warning及以上才會(huì)寫入日志文件,默認(rèn)log文件名為程序啟動(dòng)時(shí)間命名的log文件 void logInit(QString logFile = "", int logLevel = 1) {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> #ifndef _DEBUG //實(shí)現(xiàn)debug版本的時(shí)候,輸出到終端;release版本的時(shí)候輸出到日志文件 if ((logLevel < 0) || (logLevel > 3)) {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> m_LogLevel = 1; } else {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> m_LogLevel = logLevel; } if (!logFile.isEmpty()) {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> m_LogFile = logFile; } qInstallMessageHandler(customMessageHandler); #endif }}#endif // LOG_H#ifndef LOG_H #define LOG_H #include <QFile> #include <QTextStream> #include <QDateTime> #include <QMutex> //選擇屏幕打印還是輸出到文件可以根據(jù)這個(gè)宏控制或者控制函數(shù)調(diào)用位置都可以 //#define _DEBUG //默認(rèn)調(diào)試級(jí)別為warning,即小于warning級(jí)別的都不會(huì)寫入日志文件 //只有release版本的時(shí)候,才會(huì)輸出到日志,debug版本正常輸出到終端。 namespace QT_LOG { //默認(rèn)文件名為當(dāng)前時(shí)間命名的log文件 static int m_LogLevel = 1; static QString m_LogFile = QString("%1.log").arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmss")); QMutex m_LogMutex; void customMessageHandler(QtMsgType type , const QMessageLogContext &context , const QString &msg) { //設(shè)置輸出日志級(jí)別,小于該級(jí)別,將不會(huì)寫入日志文件,默認(rèn)是warning級(jí)別,即debug信息不會(huì)寫入日志文件 if (type < m_LogLevel) { return; } QString log_info; switch (type) { case QtDebugMsg: log_info = QString("%1[Debug]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); break; case QtWarningMsg: log_info = QString("%1[Warning]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); break; case QtCriticalMsg: log_info = QString("%1[Critical]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); break; case QtFatalMsg: log_info = QString("%1[Fatal]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); abort(); case QtInfoMsg: log_info = QString("%1[Info]:").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); break; } log_info += QString(context.file) + QString(context.line) + QString("%1").arg(msg); //為了線程安全 m_LogMutex.lock(); QFile outFile(m_LogFile); outFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text); QTextStream ts(&outFile); ts << log_info << endl; outFile.close(); m_LogMutex.unlock(); } //默認(rèn)調(diào)試級(jí)別為warning及以上才會(huì)寫入日志文件,默認(rèn)log文件名為程序啟動(dòng)時(shí)間命名的log文件 void logInit(QString logFile = "", int logLevel = 1) { #ifndef _DEBUG //實(shí)現(xiàn)debug版本的時(shí)候,輸出到終端;release版本的時(shí)候輸出到日志文件 if ((logLevel < 0) || (logLevel > 3)) { m_LogLevel = 1; } else { m_LogLevel = logLevel; } if (!logFile.isEmpty()) { m_LogFile = logFile; } qInstallMessageHandler(customMessageHandler); #endif } } #endif // LOG_H
調(diào)用,包含頭文件后直接調(diào)用參數(shù)即可:
QT_LOG::logInit();//或者QT_LOG::logInit("log.txt", 2);QT_LOG::logInit(); //或者 QT_LOG::logInit("log.txt", 2);
3、問題
可能不通Qt版本提供的回調(diào)函數(shù)有差異,我們通過qInstallMessageHandler進(jìn)行源碼查看,看下回調(diào)函數(shù)的樣式,實(shí)現(xiàn)對(duì)應(yīng)的回調(diào)函數(shù)進(jìn)行測(cè)試即可:
4、結(jié)果與擴(kuò)展思路
這個(gè)是我使用我上面封裝的函數(shù)后生成的日志文件,每一次啟動(dòng)創(chuàng)建一個(gè),暫時(shí)沒有考慮定時(shí)分割創(chuàng)建新文件等問題,如果有需求可以調(diào)整回調(diào)函數(shù)進(jìn)行調(diào)試:
針對(duì)上面的日志我們還可以加一些定時(shí)任務(wù)或者直接通過內(nèi)存數(shù)據(jù)庫通過線程安全的方式直接存儲(chǔ)到數(shù)據(jù)庫中,這樣便于分布式存儲(chǔ)和分析操作日志。
以上就是Qt5實(shí)現(xiàn)qDebug日志信息寫入日志文件的詳細(xì)內(nèi)容,更多關(guān)于Qt5 qDebug日志信息寫入文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解c/c++鏈?zhǔn)蕉褩C枋鲞M(jìn)制轉(zhuǎn)換問題示例
這篇文章主要為大家介紹了c/c++鏈?zhǔn)蕉褩C枋鲞M(jìn)制轉(zhuǎn)換問題示例解析有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11QT Creator+OpenCV實(shí)現(xiàn)圖像灰度化的示例代碼
這篇文章主要為大家詳細(xì)介紹了QT如何利用Creator和OpenCV實(shí)現(xiàn)圖像灰度化效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-12-12C語言詳解鏈?zhǔn)疥?duì)列與循環(huán)隊(duì)列的實(shí)現(xiàn)
隊(duì)列(Queue)與棧一樣,是一種線性存儲(chǔ)結(jié)構(gòu),它具有如下特點(diǎn):隊(duì)列中的數(shù)據(jù)元素遵循“先進(jìn)先出”(First In First Out)的原則,簡(jiǎn)稱FIFO結(jié)構(gòu)。在隊(duì)尾添加元素,在隊(duì)頭刪除元素,本篇來講解鏈?zhǔn)疥?duì)列與循環(huán)隊(duì)列的實(shí)現(xiàn)2022-04-04C++寫時(shí)拷貝實(shí)現(xiàn)原理及實(shí)例解析
這篇文章主要介紹了C++寫時(shí)拷貝實(shí)現(xiàn)原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06vc中float與DWORD的互想轉(zhuǎn)換實(shí)現(xiàn)代碼
這篇文章主要介紹了vc中float與DWORD的互想轉(zhuǎn)換實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-06-06