QT处理日志文件

news2024/11/24 11:14:01

由于实际生产需要,软件系统的运行,会产生大量的日志文件,有时候一天就能产生超过百万条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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

excel日期函数篇2

1、DATE(year,month,day)&#xff1a;根据年、月、日三个数值返回其表示的日期 2、DATEVALUE(date_text)&#xff1a;返回由文本字符串表示的日期的十进制数字 处理时间的时候&#xff0c;如果得到的是字符串格式&#xff0c;要将其转换为日期进行相关操作。excel函数里是使用文…

MinGW编译运行报错RTTI symbol not found for class ‘XXX‘

最近在调试程序时莫名的出现图中报错&#xff1a; 还遇到过for class QObject&#xff0c;在此记录一下&#xff0c;排查后发现&#xff0c;原因都是有资源被重复释放导致的。

intelij idea 2023 创建java web项目

1.点击New Project 2.创建项目名称为helloweb &#xff0c;jdk版本这里使用8&#xff0c;更高版本也不影响工程创建 点击create 3.新建的工程是空的&#xff0c;点击File-> Project Structure 4.点击Modules 5.点击加号&#xff0c;然后键盘输入web可以搜索到web模块&…

69 # 强制缓存的配置

强制缓存 强制缓存&#xff1a;以后的请求都不需要访问服务器&#xff0c;状态码为 200协商缓存&#xff1a;每次都判断一下&#xff0c;告诉是否需要找缓存&#xff0c;状态码为 304 默认强制缓存&#xff0c;不缓存首页&#xff08;如果已经断网&#xff0c;那这个页面应该…

Python三行代码实现json转Excel

最近重保&#xff0c;经常需要通过Excel上报威胁事件。安全设备的告警很多都是json格式的&#xff0c;就需要将json转成Excel。 用Python将json转成excel也就三行代码的事&#xff0c;先将json串导入形成字典对象&#xff0c;再通过pandas转成DataFrame直接输出excel。 实现如下…

windows电脑系统自带的画图工具如何实现自由拼图

1.首先选中你要拼接的第一张图片&#xff0c;右键选着编辑&#xff0c;会自动打开自带的画图工具 然后就是打开第一张图片&#xff0c;如下图所示 接着就是将画布托大&#xff0c;如下图所示。 然后点击选择&#xff0c;选择下面的空白区域&#xff0c;选着区域的范围要比准备拼…

智能楼宇综合布线实训室建设方案

一、楼宇智能综合布线实训室方案概述 楼宇智能综合布线实训室方案旨在为学生提供一个真实的学习和实践环境&#xff0c;以培养他们在楼宇智能综合布线领域的实际操作能力和技能。以下是一个概述&#xff1a; 1. 培养目标&#xff1a;培养学生在楼宇智能综合布线方面的综合能力…

耳朵小戴哪种耳机,佩戴舒适度最好的骨传导蓝牙耳机分享

亲爱的小伙伴们&#xff01;这些精心挑选的骨传导耳机绝对能给你带来全新的耳机体验。告别堵塞的耳道和细菌的困扰&#xff0c;让音乐与你完美融合&#xff01;不管你是运动爱好者、音乐发烧友还是生活达人&#xff0c;这些骨传导耳机都能满足你的需求。快行动起来&#xff0c;…

Freertos学习

一、概念 实时操作系统&#xff0c;要求一个高的实时性&#xff0c;就不是像在一个死循环中放俩函数了。而是创建俩任务&#xff0c;也叫做俩进程&#xff0c;高速的轮流执行&#xff0c;提高实时性。 二、创建任务

低代码开发ERP:精打细算,聚焦核心投入

企业数字化转型已经成为现代商业环境中的一项关键任务。如今&#xff0c;企业面临着日益激烈的竞争和不断变化的市场需求。在这样的背景下&#xff0c;数字化转型不仅是企业生存的必然选择&#xff0c;也是取得竞争优势和实现可持续发展的关键因素。 在数字化转型的过程中&…

前端对文件转换处理的一些常用方法

文章目录 0&#xff0c;前言1&#xff0c;将图片的url网络链接(http://) 转为base64格式2&#xff0c;将base64的图片数据转换为file文件3&#xff0c;将以base64的图片数据转换为Blob4&#xff0c;将file文件转化为base645&#xff0c;将file文件转换为Blob6&#xff0c;获取文…

postmarketOS

主步骤 #以下全程插入usb线 fastboot devices fastboot getvar all fastboot erase userdata fastboot erase system fastboot erase cachepmbootstrap init pmbootstrap installpmbootstrap flasher flash_rootfs --partition userdata pmbootstrap flasher flash_kernel…

盘点哪些好用的开放式耳机有哪些?开放式蓝牙耳机排行榜推荐

​你是否厌倦了传统耳机的束缚&#xff1f;是否渴望一种更为自由的听音体验&#xff1f;开放式耳机&#xff0c;将为你打开一扇全新的听觉大门。开放式耳机采用不入耳设计&#xff0c;让你在享受音乐的同时&#xff0c;保持对外界的感知&#xff0c;随时随地&#xff0c;尽享自…

图片展示 JAVA

利用Java中提供的 ImageIcon类和JLabel类加载与显示电脑路径中的图片&#xff0c;并最终展示在JFrame类窗口中。 代码&#xff1a; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel;public class Main extends JFrame {//继承父类Jframe…

智能画笔:如何利用AI绘画API打造独特的创作风格

在当今数字化时代&#xff0c;人工智能的迅猛发展正深刻地影响着各个领域&#xff0c;艺术创作也不例外。AI绘画 API 作为一种创新的工具&#xff0c;为艺术家提供了独特的机会&#xff0c;使他们能够在创作过程中借助人工智能技术&#xff0c;打造出独具个性的创作风格。本文将…

Linux系统中lib64文件夹下包含:动态链接库,静态链接库,内核模块等

lib64 目录对系统稳定运行有重要作用。 目录 lib64文件动态链接库静态链接库内核模块 lib64文件 lib64 文件夹存放主要是可被程序直接加载并使用的 64 位代码模块,包括动态库、静态库、内核模块等,这些文件对程序运行都至关重要。 在 Linux 系统中,lib64 文件夹通常用于存放…

阿里巴巴面试高频题:JVM内存模型通俗解释!

大家好&#xff0c;我是你们的小米&#xff0c;今天我要和大家一起来探讨一个热门话题——JVM内存模型&#xff01;作为计算机科班出身的小米&#xff0c;一直对技术充满热情&#xff0c;喜欢和大家分享各种有趣的知识。最近在准备阿里巴巴的面试时&#xff0c;遇到了一个非常有…

电力系统基础知识(一)—电力系统概述

1、电压 也称作电势差或电位差&#xff0c;是衡量单位电荷在静电场中由于电势不同所产生的能量差的物理量。其大小等于单位正电荷因受电场力作用从A点移动到B点所做的功,电压的方向规定为从高电位指向低电位。其单位为伏特(V,简称伏),常用单位还有千伏(kV)、毫伏(mV)、微伏(uV…

如何选择适合企业的会计软件:关键因素解析

会计软件的出现&#xff0c;帮助企业解决了一些繁杂琐碎的财务工&#xff0c;提高企业财务管理效率。因此会计软件受到了越来越多的企业的青睐。会计软件市场也越来越壮大&#xff0c;那么企业该如何挑选到适合自己的会计软件呢&#xff1f; 会计软件挑选关键因素 1. 业务需求…

比较海思麒麟810与高通骁龙855的优劣

海思麒麟810与高通骁龙855可以从以下几方面进行比较: 一、CPU比较 海思麒麟810还是高通骁龙855——哪个处理器更快?在这个比较中,我们观察了差异,并分析了这两个CPU中哪一个更好。我们比较了技术数据和基准测试结果。 海思麒麟810有8个内核和8个线程,时钟最高频率为2.2…