ToB企服应用市场:ToB评测及商务社交产业平台

标题: 使用C++和QT实现Log自定义日志系统 [打印本页]

作者: 金歌    时间: 2024-2-15 16:26
标题: 使用C++和QT实现Log自定义日志系统
MyLog

说明



警告


开发环境


GitHub


问题解决


需求


结构



思路


关键代码

MyLog.h

  1. #ifndef MYLOG_H
  2. #define MYLOG_H
  3. #include <iostream>
  4. #include <QDateTime>
  5. #include <QMutexLocker>
  6. #include <QDir>
  7. #include <QTimer>
  8. #include <QTextStream>
  9. //最大保存文件大小
  10. const int g_logLimitSize = 5;
  11. class MyLog
  12. {
  13. public:
  14.     MyLog();
  15.     ~MyLog();
  16.     static MyLog* getInstance();
  17.     //消息处理函数
  18.     static void messageHandler(QtMsgType type,
  19.                                    const QMessageLogContext& context,
  20.                                    const QString& msg);
  21. public:
  22.     //打开并备份之前的日志文件
  23.     void openAndBackupLogFile();
  24.     void checkLogFiles();
  25.     void autoDeleteLog();
  26.     //安装消息处理函数
  27.     void installMessageHandler();
  28.     //卸载消息处理函数,并释放资源
  29.     void uninstallMessageHandler();
  30. private:
  31.     //日志文件夹目录
  32.     QDir logDir;
  33.     //重命名日志文件使用的定时器
  34.     QTimer renameLogFileTimer;
  35.     //刷新输出到日志文件的定时器
  36.     QTimer flushLogFileTimer;
  37.     //日志文件的创建时间
  38.     QDate logFileCreateDate;
  39.     //日志文件
  40.     static QFile* logFile;
  41.     //输出日志
  42.     static QTextStream* logOut;
  43.     //日志锁
  44.     static QMutex logMutex;
  45.     static QScopedPointer<MyLog> self;
  46. };
  47. #endif // MYLOG_H
复制代码
MyLog.cpp

<blockquote>[code]#include "mylog.h"#include#include#define LOG 1//初始化静态变量QMutex MyLog::logMutex;QFile* MyLog::logFile = NULL;QTextStream* MyLog::logOut = NULL;QScopedPointer MyLog::self;//定义单例模式MyLog* MyLog::getInstance(){    //还没有创建实例    if(self.isNull())    {        //加把锁,只能有一个线程访问        static QMutex mutex;        //自动加解锁        QMutexLocker locker(&mutex);        //再次判断有没有实例,防止等待的时间中有线程获取到实例了        if(self.isNull())        {            self.reset(new MyLog);        }    }    return self.data();}MyLog::MyLog(){    //设置日志文件夹的路径,./exe    logDir.setPath("log");    //获取日志的绝对路径    QString logPath = logDir.absoluteFilePath("today.log");    //获取日志文件创建的时间    //保存日志文件最后的修改时间    logFileCreateDate = QFileInfo(logPath).lastModified().date();    //打开并备份日志文件    openAndBackupLogFile();    //每10分钟检查一次日志文件创建的时间    renameLogFileTimer.setInterval(1000 * 60 *1000);    renameLogFileTimer.start();    //处理超时事件,10分钟重复一次    QObject::connect(&renameLogFileTimer,&QTimer::timeout,[this](){        QMutexLocker locker(&MyLog::logMutex);        openAndBackupLogFile();        checkLogFiles();        autoDeleteLog();    });    //定时刷新日志输出到日志文件,1秒1刷新    flushLogFileTimer.setInterval(1000);    flushLogFileTimer.start();    QObject::connect(&flushLogFileTimer,&QTimer::timeout,[](){#if LOG        // 测试不停地写入当前时间到日志文件        qDebug() flush();        }    });}MyLog::~MyLog(){    if(NULL != logFile)    {        logFile->flush();        logFile->close();        logOut = NULL;        logFile = NULL;    }}//打开并备份之前的日志文件void MyLog:penAndBackupLogFile(){    //有可能一天多次打开日志文件,使用追加的方式打开    //目录不存在,创建目录    if(!logDir.exists())    {        logDir.mkpath(".");    }    //log.txt的路径    QString logPath = logDir.absoluteFilePath("today.log");    //程序启动的时候,logfile为空    if(logFile == NULL)    {        //创建新的        logFile = new QFile(logPath);        //只写,追加的方式打开日志文件        //成功,创建文本流对象与日志文件关联,向日志文件写内容        logOut = (logFile->open(QIODevice::WriteOnly | QIODevice::Text |QIODevice::Append)) ? new QTextStream(logFile) : NULL;        if(logOut != NULL)        {            //设置编码格式            logOut->setCodec("UTF-8");        }        //日志文件第一次创建,创建日期无效,设置为修改日期        if(logFileCreateDate.isNull())        {            logFileCreateDate = QDate::currentDate();        }    }    //程序运行的时候,创建日期不是当前日期,更新日期,重命名,备份老的并生成新的log.txt    if(logFileCreateDate != QDate::currentDate())    {        //先刷新缓冲区,确保内容先输出到文件里        logFile->flush();        logFile->close();        //更新日期到备份文件        QString backUpLogPath = logDir.absoluteFilePath(logFileCreateDate.toString("yyyy-MM-dd.log"));;        //备份原来的日志        QFile::copy(logPath,backUpLogPath);        //删除原来的日志文件        QFile::remove(logPath);        //创建新的log.txt,进行更新        //只写,截断的方式打开日志        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");        }    }}//检查文件大小void MyLog::checkLogFiles(){    //日志文件大小超过5m,备份并重新创建日志文件    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);        //创建新的日志文件        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");        }    }}//自动删除超过时间的日志文件void MyLog::autoDeleteLog(){    //当前时间    QDateTime now = QDateTime::currentDateTime();    //基准,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;        }        //将文件名解析为日期对象        dateTime2 = QDateTime::fromString(f.baseName(),"yyyy-MM-dd");        //大于30天,删除        if(dateTime2 < dateTime1)        {            dir.remove(f.absoluteFilePath());        }    }}//定义消息处理函数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        //输出到控制台        std::cout




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4