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-8
        in.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 object
    edit->setPlainText("This is a test text for QPlainTextEdit.\nIt may have multiple lines.\nSome lines may contain the word function."); // set some plain text
    QString text = edit->toPlainText(); // get the plain text content
    QStringList lines = text.split("\n"); // split the text by newline
    QRegularExpression re("\\bfunction\\b"); // create a regular expression object, using \b to match word boundaries
    int count = 0; // the number of lines that match the regular expression
    int index = -1; // the index of the first matching line
    while ((index = lines.indexOf(re, index + 1)) != -1) { // loop through the lines, using indexOf() method to find the matching line
        count++; // increase the count
        qDebug() << "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 count
    return 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/82401.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

i.MX6ULL开发板无法进入NFS挂载文件系统的解决办法

问题 使用NFS网络挂载文件系统后卡住无法进入系统。 解决办法 此处不详细讲述NFS安装流程 查看板卡挂载在/home/etc/rc.init下的自启动程序 进入到../../home/etc目录下&#xff0c;查看rc.init文件&#xff0c;首先从第一行排查&#xff0c;查看/home/etc/netcfg文件代码内容&…

回归预测 | MATLAB实现FA-SVM萤火虫算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现FA-SVM萤火虫算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现FA-SVM萤火虫算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本介绍…

阿里云故障洞察提效 50%,全栈可观测建设有哪些技术要点?

本文根据作者在「TakinTalks 稳定性社区 」公开分享整理而成 #一分钟精华速览# 全栈可观测是一种更全面、更综合和更深入的观测能力&#xff0c;能协助全面了解和监测系统的各个层面和组件&#xff0c;它不仅仅是一个技术上的概念&#xff0c;更多地是技术与业务的结合。在“…

Zoho Books的安全性和数据保护:财务信息安全的保障措施揭秘

在信息化时代&#xff0c;如何保障企业信息安全是十分重要的问题&#xff0c;尤其是财务信息。财务管理工具的安全性是否有保障是许多用户担心的问题。 Zoho Books财务管理工具为客户提供了一系列的数据保护和安全措施&#xff0c;以确保客户财务信息的安全。 1. 采用高度加密…

MySQL流程控制

流程控制 顺序结构&#xff1a; 程序从上往下依次执行分支结构&#xff1a; 程序按条件进行选择执行&#xff0c;从两条或多条路径中选择一条执行。循环结构&#xff1a; 程序满足一定条件下&#xff0c;重复执行一组语句 针对于MySQL的流程控制语句主要有3类。注意&#xff…

js ajax 国内快速 映像

ajax 快速 映像 https://www.bootcdn.cn/ axios入门和axios基本请求方式 https://blog.csdn.net/m0_68997646/article/details/127438174 使用 jsDelivr CDN: <script src"https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>因为我们国…

jps(JVM Process Status Tool):虚拟机进程状况工具

jps&#xff08;JVM Process Status Tool&#xff09;&#xff1a;虚拟机进程状况工具 列出正在运行的虚拟机进程&#xff0c;并显示虚拟机执行主类名称&#xff08;Main Class&#xff0c;main()函数所在的类&#xff09;以及这些进程的本地虚拟机唯一ID&#xff08;LVMID&am…

第5步---MySQL的DQL查询语句

第5步---MySQL的DQL查询语句 DQL 数据库查询语言 1.基本的查询语句 1.完整得查询得语句 简化版的查询语句 select * from 表名 where 条件; 2.创建用于测试的表 1.创建测试数据 -- DQL -- 创建测试表 DROP TABLE IF EXISTS product; CREATE TABLE IF NOT EXISTS product( pi…

分代收集 + 垃圾回收算法

分代假说 1. 弱分代假说&#xff08;Weak Generational Hypothesis&#xff09;&#xff1a;绝大多数对象都是朝生夕灭的 2. 强分代假说&#xff08;Strong Generational Hypothesis&#xff09;&#xff1a;熬过越多次垃圾收集过程的对象就越难以消亡 3. 跨代引用假说&…

Java开发面试题 | 2023

Java基础 接口和抽象类的区别&#xff1f;Java动态代理HashMap 底层实现及put元素的具体过程currenthashmap底层实现原理&#xff1f;map可以放null值吗&#xff0c;currenthashmap为什么不能放null值synchronze和reetrantlock区别&#xff1f;怎样停止一个运行中的线程&#…

提高批量爬虫工作效率

大家好&#xff01;作为一名专业的爬虫程序员&#xff0c;我今天要和大家分享一些关于提高批量爬虫工作效率的实用技巧。无论你是要批量采集图片、文本还是视频数据&#xff0c;这些经验都能帮助你在大规模数据采集中事半功倍。废话不多说&#xff0c;让我们开始吧&#xff01;…

MATLAB | 七夕节用MATLAB画个玫瑰花束叭

Hey又是一年七夕节要到了&#xff0c;每年一次直男审美MATLAB绘图大赛开始hiahiahia&#xff0c;真的这些代码越写越不知道咋写&#xff0c;又不想每年把之前的代码翻出来再发一遍&#xff0c;于是今年又对我之前写的老代码进行了点优化组合&#xff0c;整了个花球变花束&#…

Transformer是什么,Transformer应用

目录 Transformer应用 Transformer是什么 Transformer应用:循环神经网络 语言翻译&#xff1a;注重语句前后顺序 RNN看中单个特征&#xff1b; CNN&#xff1a;看中特征之间时序性 模型关注不同位置的能力 Transformer是什么 Transformer是一个利用注意力机制来提高模型…

如何在pycharm中指定GPU

如何在pycharm中指定GPU 作者:安静到无声 个人主页 目录 如何在pycharm中指定GPU打开编辑配置点击环境变量添加GPU配置信息推荐专栏在Pycharm运行程序的时候,有时候需要指定GPU,我们可以采用以下方式进行设置: 打开编辑配置 点击环境变量 添加GPU配置信息 添加名称:CU…

新的 Python URL 解析漏洞可能导致命令执行攻击

Python URL 解析函数中的一个高严重性安全漏洞已被披露&#xff0c;该漏洞可绕过 blocklist 实现的域或协议过滤方法&#xff0c;导致任意文件读取和命令执行。 CERT 协调中心&#xff08;CERT/CC&#xff09;在周五的一份公告中说&#xff1a;当整个 URL 都以空白字符开头时&…

华为网络篇 RIP路由标记-31

难度2复杂度2 目录 一、实验原理 二、实验拓扑 三、实验步骤 四、实验过程 总结 一、实验原理 路由标记tag是用于进行路由过滤的&#xff0c;它给相关的路由打标记&#xff0c;然后应用于路由策略中&#xff0c;路由器会根据策略进行路由过滤。比如&#xff0c;给静态路由…

【开源项目】Stream-Query的入门使用和原理分析

前言 无意间发现了一个有趣的项目&#xff0c;Stream-Query。了解了一下其基本的功能&#xff0c;可以帮助开发者省去Mapper的编写。在开发中&#xff0c;我们会编写entity和mapper来完成业务代码&#xff0c;但是Stream-Query可以省去mapper&#xff0c;只写entity。 快速入…

在线HmacSHA256加密工具--在线获取哈希值又称摘要

具体请前往&#xff1a; 在线计算HmacSha256工具

剑指offer全集系列(1)

目录 JZ3 数组中重复的数字 JZ4 二维数组中的查找 JZ5 替换空格 JZ6 从尾到头打印链表 JZ18 删除链表的节点 JZ22 链表中倒数最后k个结点 题目为剑指offer top100题目, 欢迎大家来学习&#x1f618; JZ3 数组中重复的数字 数组中重复的数字_牛客题霸_牛客网在一个长度为…