Qt implementa el registro del archivo de registro

Visión de conjunto

Qt tiene dos formas de registrar registros. La primera es instalar un controlador de mensajes Qt personalizado para generar automáticamente mensajes de depuración, advertencias, mensajes de error críticos y fatales generados por el programa; la segunda es personalizar una clase, puede imprimir el especificado contenido en la ubicación especificada del programa.

El primer método qInstallMessageHandler

Personalice la función de procesamiento de mensajes y luego instale la función.Tenga en cuenta que los mensajes QDebug aparecerán en el archivo de registro en este momento y no se imprimirán cuando se depure el programa Qt.
main.cpp

#include "widget.h"
#include <QApplication>
#include <QMutex>
#include <QFile>
#include <QMessageLogContext>
#include <QDebug>
#include <QDateTime>

void outputMessage(QtMsgType type,const QMessageLogContext &context,const QString &msg);
int main(int argc, char *argv[])
{
    
    
    qInstallMessageHandler(outputMessage);//安装消息处理程序
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

void outputMessage(QtMsgType type,const QMessageLogContext &context,const QString &msg)
{
    
    
    static QMutex mutex;
    mutex.lock();
    QByteArray localMsg = msg.toLocal8Bit();
    QString text;
    switch (type)
    {
    
    
        case QtDebugMsg:
            text = QString("Debug:");
            break;
        case QtWarningMsg:
            text = QString("Warning:");
            break;
        case QtCriticalMsg:
            text = QString("Critical:");
            break;
        case QtFatalMsg:
            text = QString("Fatal:");
            break;
        default:
            text = QString("Debug:");
    }

    // 设置输出信息格式
       QString context_info = QString("File:(%1) Line:(%2)").arg(QString(context.file)).arg(context.line); // F文件L行数
       QString strDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
       //QString strMessage = QString("%1 %2 \t%3 \t%4").arg(text).arg(context_info).arg(strDateTime).arg(msg);
       QString strMessage = QString("%1 \t%2 \t%3").arg(text).arg(strDateTime).arg(msg);
       // 输出信息至文件中(读写、追加形式)
       QFile file(QString(QDateTime::currentDateTime().toString("yyyy-MM-dd").append("-log.txt")));
       file.open(QIODevice::ReadWrite | QIODevice::Append);
       QTextStream stream(&file);
       stream << strMessage << "\r\n";
       file.flush();
       file.close();
       // 解锁
        mutex.unlock();
}

El segundo tipo: personalizar una clase para implementar la interfaz de registro de salida

Defina una clase de registro para implementar la interfaz para generar registros en el archivo especificado y simplemente llame a la interfaz donde se debe generar el registro.
clog.h

#ifndef CLOG_H
#define CLOG_H

#include <QFile>

class  CLog : public QObject
{
    
    
    Q_OBJECT
public:

    /*!
     *  @brief 日志等级
     */
    enum CLOG_LEVEL
    {
    
    
        RINFO,               /*!<    提示  */
        RWARNING,            /*!<    警告  */
        RERROR               /*!<    错误  */
    };
    Q_FLAG(CLOG_LEVEL)

    struct LogConfig
    {
    
    
        bool isRecord2File;     /*!< 是否记录到文件 */
        int level;              /*!< 记录日志等级,大于等于此level的日志将被记录 */
    };

    CLog();

    void setLogLevel(const CLog::CLOG_LEVEL & level);
    CLog::CLOG_LEVEL getLogLevel(){
    
    return logLevel;}

    static bool init(CLog::LogConfig & logConfig);
    static bool createDir(QString dirPath);

    static void log(CLOG_LEVEL nLevel,const char * fileDesc,const char * functionDesc, int lineNum,const char* data, ...);

private:
    static QString getLeveDesc(CLOG_LEVEL level);

private:
    static bool isRecord2File;
    static bool isFileReady;
    static CLOG_LEVEL logLevel;
};

#ifdef Q_OS_WIN
#define FILE_SEPARATOR '\\'
#else
#define FILE_SEPARATOR '/'
#endif

#define FUNC_SEPARATOR '::'

#ifndef QT_NO_DEBUG
#define __FILENAME__ (strrchr(__FILE__, FILE_SEPARATOR) ? (strrchr(__FILE__, FILE_SEPARATOR) + 1):__FILE__)
#define __FUNNAME__ (strrchr(__FUNCTION__,FUNC_SEPARATOR)?(strrchr(__FUNCTION__, FUNC_SEPARATOR) + 1):__FUNCTION__)
#else
#define __FILENAME__ NULL
#define __FUNNAME__ NULL
#endif

#define CLOG_INFO(...)       CLog::log(CLog::RINFO,__FILENAME__,__FUNNAME__,__LINE__, __VA_ARGS__)
#define CLOG_WARNING(...)    CLog::log(CLog::RWARNING, __FILENAME__,__FUNNAME__, __LINE__,__VA_ARGS__)
#define CLOG_ERROR(...)      CLog::log(CLog::RERROR,__FILENAME__,__FUNNAME__,__LINE__,__VA_ARGS__)

#endif // CLOG_H

clog.cpp

#include "clog.h"

#include <QApplication>
#include <QDir>
#include <QDate>
#include <QMetaEnum>
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
#include <stdarg.h>

#include <QDebug>

const char PATH_LogPath[] = "/../logs";
const char Suffix[] = ".log";

#define MAX_LOG_LENGH 1024

bool CLog::isFileReady = false;
bool CLog::isRecord2File = true;
CLog::CLOG_LEVEL CLog::logLevel = CLog::RINFO;           //默认是info级

QFile localFile;
QMutex mutex;

CLog::CLog()
{
    
    
}

void CLog::setLogLevel(const CLog::CLOG_LEVEL &level)
{
    
    
    logLevel = level;
}

bool CLog::init(LogConfig &logConfig)
{
    
    
    isRecord2File = logConfig.isRecord2File;
    logLevel = (CLog::CLOG_LEVEL)logConfig.level;

    QString logDir = qApp->applicationDirPath() +  QString(PATH_LogPath);
    if(createDir(logDir))
    {
    
    
        QString fileName = logDir + QDir::separator() + QDate::currentDate().toString("yyyy-MM-dd") + QString(Suffix);
        localFile.setFileName(fileName);
        if(localFile.open(QFile::WriteOnly|QFile::Append|QFile::Text))
        {
    
    
            isFileReady = true;
        }
    }
    return isFileReady;
}

bool CLog::createDir(QString dirPath)
{
    
    
    QFileInfo fileInfo(dirPath);
    if(!fileInfo.exists())
    {
    
    
        QDir tmpDir;
        return tmpDir.mkpath(dirPath);
    }

    return true;
}

void CLog::log(CLOG_LEVEL nLevel, const char *fileDesc, const char *functionDesc, int lineNum, const char* data, ...)
{
    
    
    QMutexLocker locker(&mutex);
    if(isFileReady && nLevel >= logLevel)
    {
    
    
        QString recordInfo = QString("[%1]").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz"));
        recordInfo.append(getLeveDesc(nLevel));

#ifndef QT_NO_DEBUG
        recordInfo.append(QString("[%1:%2:%3]").arg(fileDesc).arg(functionDesc).arg(lineNum));
#endif
        va_list vlist;
        va_start(vlist,data);

        QByteArray byteArray;
#if defined(Q_OS_WIN)
        int recordLen = _vscprintf(data,vlist);
        byteArray.resize(recordLen);
#else
        byteArray.resize(1024);
#endif
        vsprintf(byteArray.data(),data,vlist);
        recordInfo.append(byteArray);
        va_end(vlist);

        recordInfo.append("\n");

        if(isRecord2File){
    
    
            localFile.write(recordInfo.toLocal8Bit().data(),recordInfo.toLocal8Bit().length());
            localFile.flush();
        }else{
    
    
//            qDebug()<<recordInfo;
        }
    }
}

QString CLog::getLeveDesc(CLog::CLOG_LEVEL level)
{
    
    
#if (QT_VERSION > 0x050500)
    static QMetaEnum metaEnum = QMetaEnum::fromType<CLog::CLOG_LEVEL>();
    return QString("[%1]").arg(metaEnum.key(level));
#else
    switch(level)
    {
    
    
        case CLOG_LEVEL::INFO:
                                return "[INFO]";
        case CLOG_LEVEL::INFO:
                                return "[WARNING]";
        case CLOG_LEVEL::INFO:
                                return "[ERROR]";
    }
#endif
}

Ejemplo de llamada simple:

    CLog::LogConfig logConfig;
    logConfig.isRecord2File = true;
    logConfig.level = 0;
    CLog::init(logConfig);
    CLOG_INFO("df2008");

Registro de salida:
[2020-12-03 13: 15: 14: 549] [RINFO] [widget.cpp: Widget: 17] df2008

Supongo que te gusta

Origin blog.csdn.net/weixin_40355471/article/details/110527027
Recomendado
Clasificación