QT處理日志文件

由于實際生產需要,軟件系統的運行,會產生大量的日志文件,有時候一天就能產生超過百萬條log記錄,那么為了能夠處理日志文件,查詢并且找到我們想要的報錯信息,因此不得不考慮怎么實現,打開大日志文件的可行方法。

在這里我采用的是內存映射的方式去讀取文件的日志信息。代碼部分如下所示:

QFile file(big_path);
qint64 fileSize = file.size(); // 獲取文件的大小
uchar *data = file.map(0, fileSize); // 將文件的全部內容映射到內存中,返回一個指向該內容的指針
file.close();//文件的關閉不會影響到我們后續的內存映射部分。if (data) { // 如果映射成功QElapsedTimer timer;timer.start();message.clear();QString text = QString::fromUtf8((char *)data, fileSize);file.unmap(data); // 取消映射ui->plainTextEdit->appendPlainText(text);message=text.split("\n");ui->label->setText("識別完成,時間為:"+QString::number(timer.elapsed()/1000)+"s");QTextCursor cursor = ui->plainTextEdit->textCursor();cursor.movePosition(QTextCursor::Start);ui->plainTextEdit->setTextCursor(cursor);//是為了實現將鼠標對應的光標移動到第一行,也就是日志的最上面。}else { // 如果映射失敗qDebug() << "映射失敗,錯誤信息:" << file.errorString(); // 打印錯誤信息QMessageBox::information(this,"提示","映射失敗,錯誤信息:"+file.errorString());}

QT里面的內存映射的機制如下:

內存映射(Memory Mapping)是一種將文件或者設備的一部分映射到進程的虛擬地址空間的技術,這樣可以方便地對文件或者設備進行讀寫操作,而不需要使用系統調用或者緩沖區。QT提供了QFileDevice類和QFile類來支持內存映射的功能,相關的方法有:

  • map(qint64 offset, qint64 size, QFileDevice::MemoryMapFlags flags = NoOptions):這個方法可以將文件或者設備的一部分映射到內存中,并返回一個指向該內存區域的指針。參數offset表示映射的起始位置,size表示映射的大小,flags表示映射的選項,比如是否保護、是否共享等。
  • unmap(uchar *address):這個方法可以取消內存映射,并釋放相關的資源。參數address表示要取消映射的內存區域的指針。
  • isMapped(uchar *address):這個方法可以檢查一個內存區域是否是由map()方法映射的。參數address表示要檢查的內存區域的指針。

除此之外,還有如何搜尋自己想要的信息,方式有以下幾種:

首先,第一種是遍歷循環每一條log信息,并在其中進行搜索,但是這樣的搜索方式只能用于小日志文件,當文件內容過多的時候,這種搜索方式的時間度是很大的。

利用for或者while等循環,來遍歷每一條的log信息。但是這個遍歷出來的速度和效率是十分慢的。

代碼實現如下所示:

 qDebug()<<pp;path_text=pp;message.clear();// 創建一個QFile對象,關聯用戶選擇的文件QFile file(path_text);// 以只讀模式打開文件if (file.open(QIODevice::ReadOnly)) {// 循環讀取每一行// 創建一個QTextStream對象,關聯文件QTextStream in(&file);// 設置流對象的編碼為UTF-8in.setCodec("UTF-8");while (!file.atEnd()) {// 讀取一行內容,轉換為QString類型QString line = QString::fromUtf8(file.readAll());// 處理或顯示每一行內容message.append(line);qDebug()<<line;ui->plainTextEdit->appendPlainText(line);//appendPlainText}// 關閉文件file.close();}else{qDebug() <<"error";}

這里為了加快讀取的速度,還專門設置了文件的編碼形式為UTF-8,來減少QT的自動識別編碼的時間,而且這個讀取文件的方式是用的Qtextstream的方式來的。

第二種就是,由于筆記本上面自帶的軟件記事本而想到的一種方式,就是記事本的查詢功能的實現,因此考慮到,將同樣的功能實現在QT里面。

另外,上面也說過了需要實現log文件的顯示,在這里我采用的是Qplaintext控件來顯示大量的文本信息。注意在這里不能采用textedit編輯器來顯示大容量的文本,它會出現錯誤。

我的界面設計如下所示:

?因為我需要查找信息,因此,要將用戶的輸入的信息進行篩選,所以我還用了一個linedit的控件來獲取輸入內容。

實現查找信息的功能的代碼部分如下圖所示:

QString goal=ui->lineEdit->text();bool result=ui->plainTextEdit->find(goal);//向下尋找
// bool result2=ui->plainTextEdit->find(goal,QTextDocument::FindBackward);//向回找if(result){QTextCursor cursor = ui->plainTextEdit->textCursor();qDebug()<<cursor.blockNumber();shunxu.push_back(cursor.blockNumber());return true;}return false;

我通過QT給的封裝函數,find函數,它會幫助我找到符合我需要的內容的所在下一行,并且將光標移動到這一行,然后我再利用QTextCursor來獲取當前光標所在行數的位置,并且打印保存下來。

因為我在前面的ui->plaintext里面,將獲取得到的log內容,通過QString里面的split(“\n”)函數的方式將原來的QString的內容按行分割成QStringList的形式保存下來。然后我通過前面獲得的行號,將對應的Qtring的行的內容,取出來,并且顯示ui->plaintext上面即可。

這種遍歷方式也最多只能達到同時遍歷幾百行的樣子。

第二種方式也可以優化,比如可以分成兩部分,多開一個線程,讓其中一個從最后開始尋找,主線程從第一行開始尋找,最后將找到的日志行數匯總到一起。相當于是一個簡單的二分法尋找。

最后第三種方式:同時遍歷很多行數

這個方法的時間復雜度是O(n),也就是隨著元素的數量增加,所需的時間也會線性增加。如果您想要一次遍歷很多行,也就是提高查找的效率,您可以使用以下的方法:

  • 使用QHash或者QMap類來存儲每個元素和它們的索引或者計數,這樣可以實現O(1)或者O(log n)的查找時間,但是需要額外的空間來存儲哈希表或者映射表。
  • 使用QStringList類的filter()方法來過濾出包含指定內容的元素,然后使用indexOf()方法或者contains()方法來獲取它們的索引或者計數,這樣可以減少遍歷的次數,但是需要創建一個新的QStringList對象。
  • 使用QRegularExpression類來創建一個正則表達式對象,表示您想要查找的內容,然后使用QStringList類的indexOf()方法或者contains()方法來查找匹配該正則表達式的元素,并獲取它們的索引或者計數,這樣可以更靈活地定義查找的條件,但是需要注意正則表達式的語法和效率。

代碼部分如下所示:

#include <QApplication>
#include <QPlainTextEdit>
#include <QDebug>
#include <QRegularExpression>int main(int argc, char *argv[]) {QApplication app(argc, argv);QPlainTextEdit *edit = new QPlainTextEdit(); // create a QPlainTextEdit objectedit->setPlainText("This is a test text for QPlainTextEdit.\nIt may have multiple lines.\nSome lines may contain the word function."); // set some plain textQString text = edit->toPlainText(); // get the plain text contentQStringList lines = text.split("\n"); // split the text by newlineQRegularExpression re("\\bfunction\\b"); // create a regular expression object, using \b to match word boundariesint count = 0; // the number of lines that match the regular expressionint index = -1; // the index of the first matching linewhile ((index = lines.indexOf(re, index + 1)) != -1) { // loop through the lines, using indexOf() method to find the matching linecount++; // increase the countqDebug() << "Found" << re.pattern() << "at line" << index + 1; // print the line number, add 1 because the index is zero-based}qDebug() << "Total" << count << "lines match" << re.pattern(); // print the total countreturn app.exec();
}

QHash和QMap都是Qt提供的關聯容器類,它們可以用來存儲鍵值對的數據結構。它們的主要區別是:

  • QHash是基于哈希表實現的,它的查找速度通常比QMap更快,但是它的鍵是以任意順序存儲的,而且它對鍵的類型有更多的要求,需要提供operator==()和qHash()函數。
  • QMap是基于跳表實現的,它的查找速度通常比QHash慢一些,但是它的鍵是以升序順序存儲的,而且它對鍵的類型只需要提供operator<()函數。

如果您需要時間度最小的一種遍歷方法,我建議您使用QHash,并且使用STL風格的迭代器來遍歷。這樣可以避免創建額外的對象,并且可以直接訪問鍵和值。例如:

QHash<QString, QStringList> hash;
// insert some data into hash
QHash<QString, QStringList>::const_iterator i = hash.constBegin();
while (i != hash.constEnd()) {QString key = i.key();QStringList value = i.value();// do something with key and value++i;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/42975.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/42975.shtml
英文地址,請注明出處:http://en.pswp.cn/news/42975.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ARM--day2(cpsr、spsr、數據搬移指令、移位操作指令、位運算操作指令、算數運算指令、比較指令、跳轉指令)

.text .global _gcd _gcd:mov r0,#9mov r1,#15b loop loop:cmp r0,r1beq stopsubhi r0,r1bhi loopsubcc r1,r0bcc loopstop:b stop.end用for循環實現1~100之間和5050 .text .global _gcd _gcd:mov r0,#0x0mov r1,#0x1mov r2,#0x64b loop loop:cmp r1,r2bhi stopadd r0,r0,r1ad…

【Unity】坐標轉換經緯度方法(應用篇)

【Unity】坐標轉換經緯度方法&#xff08;應用篇&#xff09; 解決地圖中經緯度坐標轉換與unity坐標互轉的問題。使用線性變換的方法&#xff0c;理論上可以解決小范圍內所以坐標轉換的問題。 之前有寫過[Unity]坐標轉換經緯度方法&#xff08;原理篇),在實際使用中&#xff0c…

R語言實現免疫浸潤分析(2)

原始數據承接免疫浸潤分析&#xff08;1&#xff09;&#xff0c;下面展示免疫浸潤結果&#xff1a; #直接使用IOBR包內的cell_bar_plot pic<-cell_bar_plot(input quantiseq_immo_de[1:20,], title "quanTiseq Cell Fraction") #使用ggplot2 library(ggplot2)…

大疆飛卡30運載無人機技術分享

大疆飛卡30是大疆公司面向運輸領域推出的一款專業運載無人機。它采用了優秀的設計,裝備了多種先進傳感器,以解決運輸中的難題。以下我們來了解一下其主要特點: 【應用領域】 飛卡30適用于山地救災、農業化肥施用、工程材料運送等交通不便的山區應用,也適用于海島聯通等運輸鏈…

管理類聯考——邏輯——真題篇——按知識分類——匯總篇——二、論證邏輯——削弱——第一節 推理論證

文章目錄 第七章 削弱質疑第一節 削弱-題型1-推理論證-論證為預測結果題-削弱質疑-預測-推理論證-分類1-削弱論點真題(2019-24)-削弱質疑-預測-推理論證-分類1-削弱論點真題(2019-42)-削弱質疑-預測-推理論證-分類1-削弱論點真題(2011-32)-削弱質疑-預測-推理論證-分類…

機器學習基礎之《分類算法(3)—模型選擇與調優》

作用是如何選擇出最好的K值 一、什么是交叉驗證&#xff08;cross validation&#xff09; 1、定義 交叉驗證&#xff1a;將拿到的訓練數據&#xff0c;分為訓練和驗證集。以下圖為例&#xff1a;將數據分成5份&#xff0c;其中一份作為驗證集。然后經過5次(組)的測試&#x…

通過請求頭傳數據向后端發請求

axios &#xff08;get post請求、頭部參數添加&#xff09;傻瓜式入門axios_axiospost請求參數_web_blog的博客-CSDN博客

ByteBuffer 使用

ByteBuffer 使用 1 java.nio包中的類定義的緩沖區類型2 緩沖區常用屬性2.1緩沖區的容量(capacity)2.2 緩沖區的位置(position)2.3 緩沖區的限制(limit)2.4 緩沖區的標記(mark)2.5 剩余容量 remaining/hasRemaining 3 緩沖區常用方法3.1 創建緩沖區3.1.1 allocate方法3.1.2 wrap…

【mybatis】mapper.xml中foreach的用法,含批量查詢、插入、修改、刪除方法的使用

一、xml文件中foreach的主要屬性 foreach元素的屬性主要有 collection&#xff0c;item&#xff0c;index&#xff0c;separator&#xff0c;open&#xff0c;close。 collection: 表示集合&#xff0c;數據源 item &#xff1a;表示集合中的每一個元素 index &#xff1a;用于…

blender 發射體粒子

發射體粒子的基礎設置 選擇需要添加粒子的物體&#xff0c;點擊右側粒子屬性&#xff0c;在屬性面板中&#xff0c;點擊加號&#xff0c;物體表面會出現很多小點點&#xff0c;點擊空格鍵&#xff0c;粒子會自動運動&#xff0c;像下雨一樣&#xff1b; bender 粒子系統分為兩…

【100天精通python】Day40:GUI界面編程_PyQt 從入門到實戰(完)_網絡編程與打包發布

目錄 8 網絡編程 8.1 使用PyQt 網絡模塊進行網絡通信 服務器端示例 客戶端示例 8.2 處理網絡請求和響應 9 打包和發布 9.1 創建可執行文件或安裝程序 9.2 解決依賴問題 9.3 發布 PyQt 應用到不同平臺 9.3.1 發布到 Windows 9.3.2 發布到 macOS 9.3.3 發布到 Linux 9…

sap ui5刷新頁面的方式

1.第一種 window.location.reload();2.第二種 如果你想在UI5應用程序中使用MVC模式來處理頁面刷新,可以通過重新加載當前路由來實現刷新。首先,確保你有一個Router對象實例: var oRouter = sap.ui.core.UIComponent.getRouterFor(this);然后&

[保研/考研機試] KY43 全排列 北京大學復試上機題 C++實現

題目鏈接&#xff1a; 全排列https://www.nowcoder.com/share/jump/437195121692001512368 描述 給定一個由不同的小寫字母組成的字符串&#xff0c;輸出這個字符串的所有全排列。 我們假設對于小寫字母有a < b < ... < y < z&#xff0c;而且給定的字符串中的字…

Docker vs. Kubernetes:選擇合適的場景

在決定使用 Docker 還是 Kubernetes 之前&#xff0c;讓我們看看一些實際的場景&#xff0c;以便更好地理解它們的適用性。 使用 Docker 的場景 假設您正在開發一個微服務應用程序&#xff0c;其中每個微服務都需要一些特定的依賴項和環境。在這種情況下&#xff0c;Docker 是一…

HJ6 質數因子

描述 功能:輸入一個正整數&#xff0c;按照從小到大的順序輸出它的所有質因子&#xff08;重復的也要列舉&#xff09;&#xff08;如180的質因子為2 2 3 3 5 &#xff09; 數據范圍&#xff1a; 1≤n≤210914 1≤n≤210914 輸入描述&#xff1a; 輸入一個整數 輸出描述&…

學習Vue:聲明式路由和程序式路由

在Vue.js中&#xff0c;路由與導航是構建單頁應用程序&#xff08;SPA&#xff09;的關鍵概念。在使用Vue Router時&#xff0c;您可以使用兩種方式來進行路由與導航&#xff1a;聲明式路由和程序式導航。本文將詳細介紹這兩種方式&#xff0c;幫助您理解它們的用法和優勢。 聲…

Ceph入門到精通-Aws Iam(user,role,group,policy,resource)架構圖和快速入門

-- Aws Iam(identity,user,role,group,policy,resource,)架構圖和快速入門. 【官網】&#xff1a;Cloud Computing Services - Amazon Web Services (AWS) 應用場景 aws 云服務運維,devops過程中經常涉及各項服務&#xff0c;權限&#xff0c;角色的處理。 為了更好的使用各項…

Redis在Java中的基本使用

本片將介紹 Redis 在 Java 中的基本使用 文章目錄 1、使用jedis操作redis1.1、Jedis簡介1.2、引入jedis的Maven依賴1.2、獲取連接1.3、使用實例 2、對于JedisPooled的使用2.1、使用JedisPooled2.2、關于連接池 3、SpringBoot下使用Redis3.1、引入Maven依賴3.2、配置Redis連接3.…

mac m1上系統內錄內部聲音的方法/無需安裝Blackhole

總所周知&#xff0c;m1的mac不能錄制桌面音頻&#xff0c;obsstudio都不行。 最快的解決方法就是下載飛書&#xff1a; 登陸后新建直播/視頻會議&#xff1a; 共享的時候選擇下面的兩個鉤上去就好了

6.RocketMQ之索引文件ConsumeQueue

本文著重分析為consumequeue/topic/queueId目錄下的索引文件。 1.ConsumeQueueStore public class ConsumeQueueStore {protected final ConcurrentMap<String>, ConcurrentMap<Integer>, ConsumeQueueInterface>> consumeQueueTable;public boolean load(…