QT中日志的使用案例 || 自动创建、管理、保存QT日志数据

目录

1.quiwidget.cpp

2.widget.cpp

3.widget.h

4.在需要记录日志的地方直接将信息插入即可

1. 释放 `m_fileLog` 和 `m_textStream`

1.1 为什么要关闭和删除 `m_fileLog` 和 `m_textStream`?

1.2 如果不这样做会有什么坏处?

 3. 总结

4.参考文章


需求分析:

        想实现在qt代码中对软件运行过程中容易出现的问题进行记录,将电量异常分析日志与平时详细日志进行分开存储。同时为了避免占用内存过大影响使用,需要每日对不是今天的文件夹进行清理,由于电量分析日志占用内存不大,目前,只对详细日志进行每日删除的操作以下是具体的一些实现思路。

1.quiwidget.cpp

#define TIMEMS          qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
#define TIME            qPrintable(QTime::currentTime().toString("HH:mm:ss"))
#define QDATE           qPrintable(QDate::currentDate().toString("yyyy-MM-dd"))
#define QTIME           qPrintable(QTime::currentTime().toString("HH-mm-ss"))
#define DATETIME        qPrintable(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"))
#define STRDATETIME     qPrintable(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"))
#define STRDATETIMEMS   qPrintable(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss-zzz"))
#define RECORDFILE      qPrintable(QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss"))

2.widget.cpp

void Widget::writeLog(const QString &log, bool isChargeLog) {
    QString currentDate = QDate::currentDate().toString("yyyy-MM-dd");

    // 根据isChargeLog标志判断是充电异常日志还是详细日志
    QString logDir, logFileName,logDir2;

    // 选择路径和文件名
    if (isChargeLog) {
        logDir = QString("%1\\ChargeRecord\\%2").arg(m_strExeDir).arg(QDATE);
        logFileName = QString("%1\\ChargeLog_%2.txt").arg(logDir).arg(RECORDFILE);
    } else {
        logDir = QString("%1\\DetailedRecord\\%2").arg(m_strExeDir).arg(QDATE);
        logDir2 = QString("%1\\DetailedRecord").arg(m_strExeDir);
        logFileName = QString("%1\\DetailedRecord.txt").arg(logDir);
        // 删除非今天的文件夹和文件
        cleanupOldLogs(logDir2);
    }
    // 创建文件夹
    QDir temp;
    temp.mkpath(logDir);


    // 如果文件未被创建则创建文件
    if (m_fileLog == nullptr || m_fileLog->fileName() != logFileName) {
        if (m_fileLog != nullptr) {
            delete m_fileLog;  // 删除旧的文件对象
        }
        m_fileLog = new QFile(logFileName);
        bool ok = m_fileLog->open(QIODevice::ReadWrite | QIODevice::Append);
        if (ok) {
            // 赋值stream
            if (m_textStream != nullptr) {
                delete m_textStream;  // 删除旧的流对象
            }
            m_textStream = new QTextStream(m_fileLog);
        }
    }

    // 如果文件流准备好,写入日志
    if (m_textStream != nullptr) {
        QString logWithTimestamp = QString("[%1] %2").arg(DATETIME, log); // 添加时间戳
        *m_textStream << logWithTimestamp << endl;
        m_fileLog->flush();  // 立刻写入以防崩溃

    }
}


void Widget::loadDetailedLog(){
    writeLog(QString("---------start----------"),false);
    writeLog(QString("状态转换m_nCurState【借卡:第一次交互前】 %1").arg(m_nCurState),false);
    writeLog(QString("---------end----------"),false);
}

void Widget::onBtnqqClicked()
{
    ui->widgetLocker->saveSlotJson(m_strExeDir, PARAM_FILE_NAME);
}

// 清除非今天的日志文件夹和文件
void Widget::cleanupOldLogs(const QString &logDir) {
    QDir dir(logDir);
    QStringList allDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);

    // 检查并删除所有不是今天日期的子文件夹
    for (const QString &folder : allDirs) {
        if (folder != QDate::currentDate().toString("yyyy-MM-dd")) {
            //qDebug() << "Deleting old log folder:" << folder;
            QDir oldDir(logDir + "\\" + folder);
            oldDir.removeRecursively();  // 删除该文件夹及其下的所有内容
        }
    }

    // 检查文件夹是否为空(删除空的文件夹)
    if (dir.entryList(QDir::Files).isEmpty() && dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot).isEmpty()) {
        dir.rmdir(logDir);  // 删除空文件夹
    }
}

3.widget.h

//wigdet.h

public:
    void writeLog(const QString &log, bool isChargeLog);

4.在需要记录日志的地方直接将信息插入即可

    //记录日志
    QString num = QString::number(m_stCardInInfo.stSlotParam.nNum);
    QString onsite = QString::number(m_stCardInInfo.stSlotParam.stLt100Info.ucOnsite);
    QString cardNotSite = QString::number(m_stCardInInfo.stSlotParam.nCardNotSite);
    QString enable = QString::number(m_stCardInInfo.stSlotParam.nEnable);
    QString state = QString::number(m_stCardInInfo.stSlotParam.nState);
    QString cardStatus_flag = QString::number(m_stCardOutInfo.stSlotParam.cardStatus_flag);
    QString info = QString("归还的柜门状态 num: %1, Onsite: %2, CardNotSite: %3, Enable: %4, State: %5, bindState:%6")
                   .arg(num)
                   .arg(onsite)
                   .arg(cardNotSite)
                   .arg(enable)
                   .arg(state)
                   .arg(cardStatus_flag);

    writeLog(QString("%1").arg(info),false);

1. 释放 `m_fileLog` 和 `m_textStream`

1.1 为什么要关闭和删除 `m_fileLog` 和 `m_textStream`?

在 Qt 中,`QFile` 和 `QTextStream` 都是资源管理型的类,尤其是 `QFile` 负责文件的打开、关闭和读写操作,`QTextStream` 用于在文件中执行流式写入和读取。

- **关闭文件 (`m_fileLog->close()`)**:
  `QFile` 对象打开文件后,它会保持文件句柄(资源),直到文件被显式关闭。如果在程序结束时没有关闭文件,操作系统可能会认为文件仍然在使用中,导致以下问题:
  - **文件无法正确保存**:某些数据可能没有写入磁盘。
  - **文件句柄泄漏**:每个打开的文件都占用系统资源,如果程序没有释放文件句柄,操作系统可能会因为文件句柄数目耗尽而出现错误,尤其是在打开大量文件时。
  
  关闭文件是文件操作的最佳实践,它确保所有缓冲数据被刷新到磁盘,并且释放操作系统资源。

- **删除 `m_textStream`**:
  `QTextStream` 是一个指向 `QFile` 的流对象,负责将数据写入文件。`QTextStream` 本身是一个包装对象,不负责文件的实际打开和关闭,但是它依赖于 `QFile` 的存在。如果不手动删除 `QTextStream`,它将和 `QFile` 一起被销毁,但没有显式释放内存的话,会存在内存泄漏的风险。

1.2 如果不这样做会有什么坏处?

如果我们不关闭文件和删除 `QTextStream`,会有以下几个问题:

- **内存泄漏**:如果没有删除 `m_textStream`,它指向的内存就不会被释放,导致内存泄漏。
- **文件操作不完整**:如果不关闭文件,`QFile` 可能没有正确地将所有数据写入磁盘。即使没有写入错误,某些数据可能会丢失,因为文件未被正确刷新。
- **资源泄漏**:`QFile` 需要操作系统资源(如文件句柄),如果不手动关闭文件,这些资源就不会被释放。长时间运行的程序可能会导致文件句柄耗尽,导致系统不允许再打开新文件。

 3. 总结

在析构函数中进行资源释放(关闭文件、删除流对象、删除 `ui`)是良好的编程实践,具体原因如下:

- **文件关闭**:防止文件未完全保存、文件句柄泄漏等问题。
- **删除对象**:防止内存泄漏,确保内存得到及时释放。
- **UI 删除**:确保 Qt 控件的内存被及时清理,避免内存泄漏。

### 如果不这样做的坏处:

1. **文件未关闭**:数据可能未被写入文件,文件句柄资源可能泄漏,导致文件操作出错。
2. **内存泄漏**:没有手动删除 `m_textStream` 和其他动态分配的内存,程序可能会在退出时无法释放内存。
3. **系统资源泄漏**:如果没有释放文件句柄和其他系统资源,可能会耗尽操作系统资源,导致后续无法打开新文件或其他系统操作失败。

4.参考文章

Qt之第三方库‌日志log使用(四)_qt log-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值