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