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.mzph.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适用于山地救灾、农业化肥施用、工程材料运送等交通不便的山区应用,也适用于海岛联通等运输链…

机器学习基础之《分类算法(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…

blender 发射体粒子

发射体粒子的基础设置 选择需要添加粒子的物体&#xff0c;点击右侧粒子属性&#xff0c;在属性面板中&#xff0c;点击加号&#xff0c;物体表面会出现很多小点点&#xff0c;点击空格键&#xff0c;粒子会自动运动&#xff0c;像下雨一样&#xff1b; bender 粒子系统分为两…

[保研/考研机试] 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 是一…

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(…

【BUG】docker安装nacos,浏览器却无法访问到页面

个人主页&#xff1a;金鳞踏雨 个人简介&#xff1a;大家好&#xff0c;我是金鳞&#xff0c;一个初出茅庐的Java小白 目前状况&#xff1a;22届普通本科毕业生&#xff0c;几经波折了&#xff0c;现在任职于一家国内大型知名日化公司&#xff0c;从事Java开发工作 我的博客&am…

object获取的两种方式/Object.keys使用/解构赋值

object获取的两种方式&#xff1a; data() {return {abj: {aa: {A: 1}}}},created() {console.log(this.abj.aa) //第一种console.log(this.abj["aa"]) //第二种}, Object.keys使用/解构赋值&#xff1a; return {footList: [],abj: {aa: {A: 12,AA:22},bb: {…

软件工程概述-架构师(三)

软件工程概述&#xff08;老版&#xff09; 软件开发生命周期&#xff1a; 软件定义时期&#xff1a;包括 可行性研究和详细需求分析过程&#xff0c;任务是软件工程必需完成的目标&#xff0c;具有可行问题分析、可行性研究、需求分析等。软件开发时期&#xff1a;软件的 设…

20230818 数据库自整理部分

并发事务 脏读 一个事务读取到另一事务还没有提交的数据 事务B读取了事务A还没有提交的数据 不可重复读 一个事务先后读取同一条记录&#xff0c;但是两次读取的数据不同&#xff0c;称之为不可重复读 查询出来的数据不一样 1步骤b还没有提交 3步骤b已经提交 幻读 一个…

SOLIDWORKS 2023中装配体配合的正确使用方法 硕迪科技

-SOLIDWORKS 装配体打开时是由不同的阶段和性能检查组成的。如果在创建装配体时未应用基本的配合方法&#xff0c;问题会随着时间的推移而累积&#xff0c;并且在使用时会出现明显的速度减慢。 如果您的装配体运行速度很慢&#xff0c;则很可能是在创建配合时出现了不良操作的症…

贝叶斯推理问题、MCMC和变分推理

一、说明 1.1 介绍 贝叶斯推理是统计学中的一个主要问题&#xff0c;在许多机器学习方法中也会遇到。例如&#xff0c;用于分类的高斯混合模型或用于主题建模的潜在狄利克雷分配都是在拟合数据时需要解决此类问题的图形模型。 同时&#xff0c;可以注意到&#xff0c;贝叶斯推…