欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用C++和QT實(shí)現(xiàn)Log自定義日志系統(tǒng)

 更新時(shí)間:2023年12月13日 08:41:03   作者:KanHai1024  
這篇文章主要為大家詳細(xì)介紹了如何利用C++和QT實(shí)現(xiàn)Log自定義日志系統(tǒng),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下

說明

  • 使用QT的qInstallMessageHandler函數(shù)結(jié)合qDebug,qInfo實(shí)現(xiàn)自定義的日志系統(tǒng)
  • 輸出日志到文件和控制臺(tái)
  • 自動(dòng)檢測(cè)日志文件大小
  • 自動(dòng)更新日志文件修改日期
  • 自動(dòng)備份
  • 自動(dòng)刪除一個(gè)月前的日志文件
  • 支持多線程程序
  • 支持?jǐn)U展,可輸出日志到數(shù)據(jù)庫,網(wǎng)絡(luò),或服務(wù)器
  • 支持?jǐn)U展,可使用config文件進(jìn)行配置

開發(fā)環(huán)境

win10系統(tǒng)

qtcreator4.11.1

C++11

QT5.14.2

GitHub

GitHub下 的Log文件

若不能訪問GitHub,源碼的資源包會(huì)隨文章同步發(fā)布,免費(fèi)下載

資源包較GitHub更新不及時(shí),請(qǐng)諒解

問題解決

Qt自定義日志類

需求

輸出日志信息到日志文件

更新日志的修改日期

日志文件超過一定大小備份老的創(chuàng)建新的

刪除一個(gè)月前的日志文件

結(jié)構(gòu)

思路

  • 隨便創(chuàng)建一個(gè)widget程序,放個(gè)測(cè)試按鈕
  • 主要思路是使用 qInstallMessageHandler()接管qDebug(), qWarning()等調(diào)試信息,然后將信息流存儲(chǔ)至本地日志文件,并管理日志文件
  • 先創(chuàng)建一個(gè)MyLog的類,在這里面我們實(shí)現(xiàn)自定義的日志系統(tǒng)
  • 這里依然是使用單例實(shí)現(xiàn),整個(gè)程序的日志應(yīng)該只能有一個(gè)
  • 首先實(shí)現(xiàn)單例getInstance獲取MyLog的實(shí)例
  • 下面處理MyLog的構(gòu)造函數(shù),每一次啟動(dòng)日志系統(tǒng),都要先設(shè)置日志文件的路徑,然后更新修改日期,然后打開并備份老的日志文件,打開之后,每10分鐘刷新日志文件,每1秒都將信息輸出到日志,
  • 下面實(shí)現(xiàn)這個(gè)打開并備份老的日志文件的功能openAndBackupLogFile,這里我們的日志文件以天為單位,先處理一天內(nèi)多次啟動(dòng)日志系統(tǒng)的情況,以追加的方式寫入到日志文件里即可;如果程序運(yùn)行的時(shí)候,日志系統(tǒng)的日期和程序運(yùn)行日期不統(tǒng)一,同步日志日期為程序運(yùn)行日期,生成新的日期日志,并且備份老的日志
  • 然后實(shí)現(xiàn)處理日志文件過大的問題,只要日志文件超限,備份老的,創(chuàng)建新的即可
  • 然后實(shí)現(xiàn)自動(dòng)刪除超時(shí)的日志文件,每次啟動(dòng)日志系統(tǒng)的時(shí)候,以當(dāng)前時(shí)間為基準(zhǔn),計(jì)算出1個(gè)月前的時(shí)間,遍歷日志目錄下的所有日志文件,因?yàn)槿罩疚募家詴r(shí)間命名,刪除超過1個(gè)月的日志文件即可
  • 最后,我們只需要處理信息函數(shù)即可,捕獲系統(tǒng)中的各種輸出信息,輸出到文件即可

關(guān)鍵代碼

MyLog.h

#ifndef MYLOG_H
#define MYLOG_H

#include <iostream>
#include <QDateTime>
#include <QMutexLocker>
#include <QDir>
#include <QTimer>
#include <QTextStream>


//最大保存文件大小
const int g_logLimitSize = 5;

class MyLog
{
public:
    MyLog();
    ~MyLog();

    static MyLog* getInstance();

    //消息處理函數(shù)
    static void messageHandler(QtMsgType type,
                                   const QMessageLogContext& context,
                                   const QString& msg);
public:
    //打開并備份之前的日志文件
    void openAndBackupLogFile();
    void checkLogFiles();
    void autoDeleteLog();
    //安裝消息處理函數(shù)
    void installMessageHandler();

    //卸載消息處理函數(shù),并釋放資源
    void uninstallMessageHandler();
private:
    //日志文件夾目錄
    QDir logDir;
    //重命名日志文件使用的定時(shí)器
    QTimer renameLogFileTimer;
    //刷新輸出到日志文件的定時(shí)器
    QTimer flushLogFileTimer;
    //日志文件的創(chuàng)建時(shí)間
    QDate logFileCreateDate;

    //日志文件
    static QFile* logFile;
    //輸出日志
    static QTextStream* logOut;
    //日志鎖
    static QMutex logMutex;
    static QScopedPointer<MyLog> self;
};

#endif // MYLOG_H

MyLog.cpp

#include "mylog.h"
#include<QDebug>
#include<QTextCodec>

#define LOG 1
//初始化靜態(tài)變量
QMutex MyLog::logMutex;
QFile* MyLog::logFile = NULL;
QTextStream* MyLog::logOut = NULL;
QScopedPointer<MyLog> MyLog::self;

//定義單例模式
MyLog* MyLog::getInstance()
{
    //還沒有創(chuàng)建實(shí)例
    if(self.isNull())
    {
        //加把鎖,只能有一個(gè)線程訪問
        static QMutex mutex;
        //自動(dòng)加解鎖
        QMutexLocker locker(&mutex);
        //再次判斷有沒有實(shí)例,防止等待的時(shí)間中有線程獲取到實(shí)例了
        if(self.isNull())
        {
            self.reset(new MyLog);
        }
    }
    return self.data();

}

MyLog::MyLog()
{
    //設(shè)置日志文件夾的路徑,./exe
    logDir.setPath("log");
    //獲取日志的絕對(duì)路徑
    QString logPath = logDir.absoluteFilePath("today.log");

    //獲取日志文件創(chuàng)建的時(shí)間
    //保存日志文件最后的修改時(shí)間
    logFileCreateDate = QFileInfo(logPath).lastModified().date();

    //打開并備份日志文件
    openAndBackupLogFile();

    //每10分鐘檢查一次日志文件創(chuàng)建的時(shí)間
    renameLogFileTimer.setInterval(1000 * 60 *1000);
    renameLogFileTimer.start();

    //處理超時(shí)事件,10分鐘重復(fù)一次
    QObject::connect(&renameLogFileTimer,&QTimer::timeout,[this](){
        QMutexLocker locker(&MyLog::logMutex);
        openAndBackupLogFile();
        checkLogFiles();
        autoDeleteLog();
    });

    //定時(shí)刷新日志輸出到日志文件,1秒1刷新
    flushLogFileTimer.setInterval(1000);
    flushLogFileTimer.start();

    QObject::connect(&flushLogFileTimer,&QTimer::timeout,[](){
#if LOG
        // 測(cè)試不停地寫入當(dāng)前時(shí)間到日志文件
        qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
#endif
        //刷新
        QMutexLocker locker(&MyLog::logMutex);
        if(NULL != logOut)
        {
            logOut->flush();
        }
    });
}

MyLog::~MyLog()
{
    if(NULL != logFile)
    {
        logFile->flush();
        logFile->close();
        logOut = NULL;
        logFile = NULL;
    }
}

//打開并備份之前的日志文件
void MyLog::openAndBackupLogFile()
{
    //有可能一天多次打開日志文件,使用追加的方式打開
    //目錄不存在,創(chuàng)建目錄
    if(!logDir.exists())
    {
        logDir.mkpath(".");
    }
    //log.txt的路徑
    QString logPath = logDir.absoluteFilePath("today.log");

    //程序啟動(dòng)的時(shí)候,logfile為空
    if(logFile == NULL)
    {
        //創(chuàng)建新的
        logFile = new QFile(logPath);
        //只寫,追加的方式打開日志文件
        //成功,創(chuàng)建文本流對(duì)象與日志文件關(guān)聯(lián),向日志文件寫內(nèi)容
        logOut = (logFile->open(QIODevice::WriteOnly | QIODevice::Text |QIODevice::Append)) ? new QTextStream(logFile) : NULL;

        if(logOut != NULL)
        {
            //設(shè)置編碼格式
            logOut->setCodec("UTF-8");
        }

        //日志文件第一次創(chuàng)建,創(chuàng)建日期無效,設(shè)置為修改日期
        if(logFileCreateDate.isNull())
        {
            logFileCreateDate = QDate::currentDate();
        }
    }

    //程序運(yùn)行的時(shí)候,創(chuàng)建日期不是當(dāng)前日期,更新日期,重命名,備份老的并生成新的log.txt
    if(logFileCreateDate != QDate::currentDate())
    {
        //先刷新緩沖區(qū),確保內(nèi)容先輸出到文件里
        logFile->flush();
        logFile->close();

        //更新日期到備份文件
        QString backUpLogPath = logDir.absoluteFilePath(logFileCreateDate.toString("yyyy-MM-dd.log"));;
        //備份原來的日志
        QFile::copy(logPath,backUpLogPath);
        //刪除原來的日志文件
        QFile::remove(logPath);

        //創(chuàng)建新的log.txt,進(jìn)行更新
        //只寫,截?cái)嗟姆绞酱蜷_日志
        logFile = new QFile(logPath);
        logOut = (logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) ? new QTextStream(logFile) : NULL;
        //更新為修改時(shí)間
        logFileCreateDate = QDate::currentDate();
        if(logOut != NULL)
        {
            logOut->setCodec("UTF-8");
        }
    }
}

//檢查文件大小
void MyLog::checkLogFiles()
{
    //日志文件大小超過5m,備份并重新創(chuàng)建日志文件
    if(logFile->size() > 1024* g_logLimitSize)
    {
        //清空緩沖
        logFile->flush();
        logFile->close();

        QString logPath = logDir.absoluteFilePath("today.log");
        //備份老的日志文件
        QString backUplogPath = logDir.absoluteFilePath(logFileCreateDate.toString("yyyy-MM-dd.log"));
        QFile::copy(logPath,backUplogPath);
        QFile::remove(logPath);

        //創(chuàng)建新的日志文件
        logFile = new QFile(logPath);
        logOut = (logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) ? new QTextStream(logFile) :NULL;
        logFileCreateDate = QDate::currentDate();
        if(logOut != NULL)
        {
            logOut->setCodec("UTF-8");
        }
    }
}

//自動(dòng)刪除超過時(shí)間的日志文件
void MyLog::autoDeleteLog()
{
    //當(dāng)前時(shí)間
    QDateTime now = QDateTime::currentDateTime();

    //基準(zhǔn),30天前
    QDateTime dateTime1 = now.addDays(-30);
    QDateTime dateTime2;

    QString logPath = logDir.absoluteFilePath("today.log");
    //打開日志目錄
    QDir dir(logPath);
    //獲取目錄下的所有文件信息列表
    QFileInfoList fileList = dir.entryInfoList();
    foreach(QFileInfo f, fileList)
    {
        //跳過文件名為空的文件
        if(f.baseName() == "")
        {
            continue;
        }

        //將文件名解析為日期對(duì)象
        dateTime2 = QDateTime::fromString(f.baseName(),"yyyy-MM-dd");
        //大于30天,刪除
        if(dateTime2 < dateTime1)
        {
            dir.remove(f.absoluteFilePath());
        }
    }
}


//定義消息處理函數(shù)
void MyLog::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QMutexLocker locker(&MyLog::logMutex);
        QString level;

        switch (type) {
        case QtDebugMsg:
            level = "DEBUG";
            break;
        case QtInfoMsg:
            level = "INFO";
            break;
        case QtWarningMsg:
            level = "WARN";
            break;
        case QtCriticalMsg:
            level = "ERROR";
            break;
        case QtFatalMsg:
            level = "FATAL";
            break;
        default:
            break;
        }

#if defined (Q_OS_WIN)
        QByteArray localMsg = QTextCodec::codecForName("GB2312")->fromUnicode(msg);
#else
        QByteArray localMsg = msg.toLocal8Bit();
#endif

        //輸出到控制臺(tái)
        std::cout << std::string(localMsg) << std::endl;
        if(NULL == MyLog::logOut)
        {
            return;
        }

        //輸出到日志文件
        //獲取文件名,去掉路徑
        QString fileName = context.file;
        int index = fileName.lastIndexOf(QDir::separator());
        fileName = fileName.mid(index + 1);

        //寫入日志信息
        (*MyLog::logOut) << QString("%1 - [%2] (%3:%4, %5): %6\n")
                                        .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
                                        .arg(level)
                                        .arg(fileName)
                                        .arg(context.line)
                                        .arg(context.function)
                                        .arg(msg);
}

//安裝
void MyLog::installMessageHandler()
{
    qInstallMessageHandler(MyLog::messageHandler);
}

//卸載
void MyLog::uninstallMessageHandler()
{
    qInstallMessageHandler(NULL);
}

以上就是利用C++和QT實(shí)現(xiàn)Log自定義日志系統(tǒng)的詳細(xì)內(nèi)容,更多關(guān)于C++ QT自定義日志系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • OpenCV 視頻中火焰檢測(cè)識(shí)別實(shí)踐

    OpenCV 視頻中火焰檢測(cè)識(shí)別實(shí)踐

    本文主要介紹了OpenCV 視頻中火焰檢測(cè)識(shí)別,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C/C++ 中const關(guān)鍵字的用法小結(jié)

    C/C++ 中const關(guān)鍵字的用法小結(jié)

    C++中的const關(guān)鍵字的用法非常靈活,而使用const將大大改善程序的健壯性。這篇文章主要介紹了C/C++ 中const關(guān)鍵字的用法,需要的朋友可以參考下
    2020-02-02
  • C++類與對(duì)象的詳細(xì)說明2

    C++類與對(duì)象的詳細(xì)說明2

    這篇文章主要為大家詳細(xì)介紹了C++的類與對(duì)象,使用數(shù)據(jù)庫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • 基于C語言實(shí)現(xiàn)見縫插針游戲的示例代碼

    基于C語言實(shí)現(xiàn)見縫插針游戲的示例代碼

    見縫插針游戲就是使用鼠標(biāo)左鍵點(diǎn)擊發(fā)射針,當(dāng)兩個(gè)針的夾角小于一定限制時(shí),游戲結(jié)束。本文將用C語言實(shí)現(xiàn)這一有趣游戲,感興趣的可以了解一下
    2022-11-11
  • OpenCV實(shí)現(xiàn)鼠標(biāo)在圖像上框選單目標(biāo)和多目標(biāo)

    OpenCV實(shí)現(xiàn)鼠標(biāo)在圖像上框選單目標(biāo)和多目標(biāo)

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)鼠標(biāo)在圖像上框選單目標(biāo)和多目標(biāo),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • C/C++ Qt QThread線程組件的具體使用

    C/C++ Qt QThread線程組件的具體使用

    QThread庫是QT中提供的跨平臺(tái)多線程實(shí)現(xiàn)方案,本文詳細(xì)的介紹了Qt QThread線程組件的具體使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C++中String類型的逆序方式

    C++中String類型的逆序方式

    這篇文章主要介紹了C++中String類型的逆序方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • Qt中Tab與Tree組件實(shí)現(xiàn)分頁菜單

    Qt中Tab與Tree組件實(shí)現(xiàn)分頁菜單

    本文主要介紹tabWidget選擇夾組件與TreeWidget樹形選擇組件的常用方法及靈活運(yùn)用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • MFC程序設(shè)計(jì)常用技巧匯總

    MFC程序設(shè)計(jì)常用技巧匯總

    這篇文章主要介紹了MFC程序設(shè)計(jì)常用技巧,實(shí)例匯總了MFC程序設(shè)計(jì)中常見的問題與解決方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-05-05
  • 基于Qt+opencv開發(fā)的視頻播放器示例詳解

    基于Qt+opencv開發(fā)的視頻播放器示例詳解

    這篇文章主要為大家介紹了基于Qt+opencv開發(fā)的視頻播放器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08

最新評(píng)論