Qt實現(xiàn)日志文件的滾動寫入
Qt 日志文件的滾動寫入
flyfish
日志文件的滾動寫入功能。在日志文件達到10MB時創(chuàng)建新的日志文件,并且在總?cè)罩疚募笮∵_到10GB時開始覆蓋最早的日志文件
以監(jiān)控一個文件夾的寫日志為例
日志文件創(chuàng)建與管理
初始化日志文件:在FileMonitor類的構(gòu)造函數(shù)中,會創(chuàng)建第一個日志文件。日志文件的命名格式為 “file_monitor_序號.log”,初始序號為 0。
滾動寫入機制
單個日志文件大小限制:當向當前日志文件寫入內(nèi)容使得其大小達到 10MB(通過logFileSizeLimit變量設(shè)定,值為10 * 1024 * 1024字節(jié))時,會關(guān)閉當前日志文件,增加日志文件索引,然后創(chuàng)建新的日志文件用于后續(xù)的日志記錄。
總?cè)罩疚募笮∠拗?/h3>
同時,會監(jiān)控所有日志文件的總體大小,當總大小達到 10GB(通過totalLogSizeLimit變量設(shè)定,值為10 * 1024 * 1024 * 1024字節(jié))時,會刪除最早創(chuàng)建的日志文件(通過計算最早日志文件的文件名并判斷其是否存在,若存在則刪除),以確???cè)罩疚募笮〔粫o限制增長。
日志內(nèi)容記錄
對于文件創(chuàng)建、刪除、修改等事件,會將事件發(fā)生的當前日期時間(格式為 “yyyy-MM-dd hh:mm:ss”)、事件類型(如 “File created”、“File deleted”、“File modified”)以及相關(guān)文件的路徑信息,按照特定格式寫入到當前正在使用的日志文件中。并且每次寫入后會立即刷新緩沖區(qū),確保日志內(nèi)容及時寫入文件。同時,會實時更新當前日志文件的大小信息,以便判斷是否達到單個日志文件大小限制。
#include <QCoreApplication>
#include <QFileSystemWatcher>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QDir>
#include <QFileInfo>
#include <QSet>
#include <iostream>
// FileMonitor類繼承自QObject,用于監(jiān)控指定文件夾的文件變化并記錄相關(guān)日志
class FileMonitor : public QObject {
Q_OBJECT
public:
// 構(gòu)造函數(shù),用于初始化文件監(jiān)控器相關(guān)參數(shù)
explicit FileMonitor(const QString &path, QObject *parent = nullptr)
: QObject(parent),
// 創(chuàng)建文件系統(tǒng)監(jiān)控器對象,并將其作為當前對象的子對象
watcher(new QFileSystemWatcher(this)),
rootPath(path),
// 設(shè)置單個日志文件的大小限制為10MB,這里將10MB轉(zhuǎn)換為字節(jié)數(shù)
logFileSizeLimit(static_cast<quint64>(10) * 1024 * 1024),
// 設(shè)置總?cè)罩疚募笮∠拗茷?0GB,同樣轉(zhuǎn)換為字節(jié)數(shù)
totalLogSizeLimit(static_cast<quint64>(10) * 1024 * 1024 * 1024),
currentLogFileIndex(0),
currentLogFileSize(0) {
// 將指定的監(jiān)控路徑添加到文件系統(tǒng)監(jiān)控器中
watcher->addPath(rootPath);
// 獲取監(jiān)控路徑下初始的文件列表
QDir dir(rootPath);
initialFiles = dir.entryList(QDir::Files);
// 連接文件系統(tǒng)監(jiān)控器的目錄變化信號到對應的槽函數(shù)
connect(watcher, &QFileSystemWatcher::directoryChanged, this, &FileMonitor::onDirectoryChanged);
// 連接文件系統(tǒng)監(jiān)控器的文件變化信號到對應的槽函數(shù)
connect(watcher, &QFileSystemWatcher::fileChanged, this, &FileMonitor::onFileChanged);
// 初始化日志文件,創(chuàng)建第一個日志文件
createNewLogFile();
}
private slots:
// 當監(jiān)控的目錄發(fā)生變化時調(diào)用的槽函數(shù)
void onDirectoryChanged(const QString &path) {
std::cout << "Directory changed: " << qPrintable(path) << std::endl;
// 獲取當前監(jiān)控目錄下的文件列表
QDir dir(rootPath);
QStringList currentFiles = dir.entryList(QDir::Files);
// 找出新增的文件,通過集合運算實現(xiàn)
QSet<QString> newFiles = QSet<QString>(currentFiles.begin(), currentFiles.end()).subtract(QSet<QString>(initialFiles.begin(), initialFiles.end()));
// 遍歷新增的文件,記錄文件創(chuàng)建事件到日志
for (const QString &file : newFiles) {
logEvent("File created", dir.absoluteFilePath(file));
}
// 找出被刪除的文件,同樣通過集合運算
QSet<QString> deletedFiles = QSet<QString>(initialFiles.begin(), initialFiles.end()).subtract(QSet<QString>(currentFiles.begin(), currentFiles.end()));
// 遍歷被刪除的文件,記錄文件刪除事件到日志
for (const QString &file : deletedFiles) {
logEvent("File deleted", dir.absoluteFilePath(file));
}
// 更新初始文件列表,使其為當前的文件列表,以便下次檢測文件變化
initialFiles = currentFiles;
}
// 當監(jiān)控的文件發(fā)生變化時調(diào)用的槽函數(shù)
void onFileChanged(const QString &path) {
std::cout << "File changed: " << qPrintable(path) << std::endl;
// 記錄文件修改事件到日志
logEvent("File modified", path);
}
private:
// 創(chuàng)建新的日志文件的函數(shù)
void createNewLogFile() {
// 構(gòu)造新的日志文件名,格式為:file_monitor_序號.log
QString logFileName = "file_monitor_" + QString::number(currentLogFileIndex) + ".log";
currentLogFile.setFileName(logFileName);
// 如果日志文件已經(jīng)存在,獲取其大小并更新當前日志文件大小變量
if (currentLogFile.exists()) {
currentLogFileSize = currentLogFile.size();
} else {
currentLogFileSize = 0;
}
// 打開或創(chuàng)建日志文件,如果失敗則輸出錯誤信息
if (!currentLogFile.open(QIODevice::Append | QIODevice::Text)) {
std::cerr << "Failed to open/create log file: " << qPrintable(logFileName) << std::endl;
}
}
// 記錄日志事件的函數(shù)
void logEvent(const QString &event, const QString &path) {
// 創(chuàng)建文本流對象,用于向當前日志文件寫入內(nèi)容
QTextStream out(¤tLogFile);
// 寫入當前日期時間、事件類型和文件路徑信息到日志文件
out << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")
<< " - " << event << ": " << path << "\n";
currentLogFile.flush();
// 計算剛寫入的日志字符串的大小,先讀取文本流中的內(nèi)容
QString logString = out.readAll();
// 如果讀取為空,說明可能是因為剛剛寫入還未緩存,重新構(gòu)造日志字符串
if (logString.isEmpty()) {
logString = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")
+ " - " + event + ": " + path + "\n";
}
// 更新當前日志文件的大小,將日志字符串轉(zhuǎn)換為UTF-8編碼后計算其字節(jié)數(shù)并累加到當前日志文件大小變量
currentLogFileSize += logString.toUtf8().size();
// 檢查當前日志文件大小是否達到單個日志文件大小限制
if (currentLogFileSize >= logFileSizeLimit) {
// 關(guān)閉當前日志文件
currentLogFile.close();
// 增加日志文件索引,用于創(chuàng)建下一個新的日志文件
++currentLogFileIndex;
// 檢查是否超過了總?cè)罩疚募笮∠拗疲绻^則刪除最早的日志文件
if (currentLogFileIndex * logFileSizeLimit > totalLogSizeLimit) {
QString oldestLogFileName = "file_monitor_" + QString::number(currentLogFileIndex - totalLogSizeLimit / logFileSizeLimit) + ".doc";
if (QFile::exists(oldestLogFileName)) {
QFile::remove(oldestLogFileName);
}
}
// 創(chuàng)建新的日志文件
createNewLogFile();
}
}
// 文件系統(tǒng)監(jiān)控器對象,用于監(jiān)控指定路徑下的文件和目錄變化
QFileSystemWatcher *watcher;
// 監(jiān)控的根路徑
QString rootPath;
// 初始的文件列表,用于對比檢測文件的新增和刪除情況
QStringList initialFiles;
// 以下是新增的日志管理相關(guān)成員變量
// 當前正在使用的日志文件對象
QFile currentLogFile;
// 單個日志文件的大小限制,單位為字節(jié)
quint64 logFileSizeLimit;
// 總?cè)罩疚募笮∠拗?,單位為字?jié)
quint64 totalLogSizeLimit;
// 當前日志文件的索引,用于區(qū)分不同的日志文件
quint64 currentLogFileIndex;
// 當前日志文件的大小,單位為字節(jié),用于實時監(jiān)控文件大小是否達到限制
quint64 currentLogFileSize;
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 獲取命令行參數(shù),如果有參數(shù)則將其作為監(jiān)控路徑,否則默認監(jiān)控根目錄
QString watchPath = (argc > 1)? QString::fromLocal8Bit(argv[1]) : "/";
// 創(chuàng)建文件監(jiān)控對象,傳入監(jiān)控路徑
FileMonitor monitor(watchPath);
// 運行應用程序的事件循環(huán),開始監(jiān)控文件和目錄變化并記錄日志
return a.exec();
}
#include "main.moc"
到此這篇關(guān)于Qt實現(xiàn)日志文件的滾動寫入的文章就介紹到這了,更多相關(guān)Qt日志文件滾動寫入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Cocos2d-x保存用戶游戲數(shù)據(jù)CCUserDefault類使用實例
這篇文章主要介紹了Cocos2d-x保存用戶游戲數(shù)據(jù)CCUserDefault類使用實例,需要的朋友可以參考下2014-09-09
delete[] p->elems和free(p->elems)區(qū)別介紹
delete[]和free()都是釋放內(nèi)存的函數(shù),但它們具有不同的使用方法和適用情況,這篇文章主要介紹了delete[] p->elems和free(p->elems)有什么區(qū)別,需要的朋友可以參考下2023-04-04
深入分析父子線程、進程終止順序不同產(chǎn)生的結(jié)果
本篇文章是對父子線程、進程終止順序不同產(chǎn)生的結(jié)果進行了詳細的分析介紹,需要的朋友參考下2013-05-05
C++ sdl實現(xiàn)渲染旋轉(zhuǎn)視頻的方法分享
一般情況下播放視頻時不需要旋轉(zhuǎn),但是如果是移動端錄制的視頻有時會出現(xiàn)rotate參數(shù),且視頻寬高也是互換的。所以本文為大家準備了利用sdl實現(xiàn)渲染旋轉(zhuǎn)視頻的方法,需要的可以參考一下2022-12-12

