QT QZipReader改进,以支持大于2G的zip文件

QZipReader对ZIP文件读取非常方便好用。即使在最新版的QT 6.6.1里,仍然存在一些问题:对于大于2G的zip文件不支持。

虽然有标准zlib可调用,但包装成一个易用且功能成熟的zip解压功能库,还是有很大的工作量,也需要有一定的经验。

于是,直接找到QT的QZipReader相关的源码文件,单独做成一个Compress工具包,方便BUG调试,其次,将来再整合进7z解压等功能。

把原来的两个头文件和一个Cpp文件,整合成两个文件:QZip.h和QZip.cpp。

把QZipReader改名为ZipReader,以避免与QT自带的头文件和DLL产生冲突。

代码工程结构如下图:

代码调试过程,就不截图了。主要修改了两个方法:

1、void ZipReaderPrivate::scanFiles()

把这些变量的类型由int纠正为正确的数据型,这就是不支持超过2G的zip文件原因。

        qint64 i = 0;
    uint start_of_directory = -1;
    ushort num_dir_entries = 0;

说明原来代码还是有一些基本规范质量问题,也不知道是有意的,还是无意的,或者是发现问题了,但没有人手去分析与修改。

2、QByteArray ZipReader::fileData(const QString &fileName)

问题跟前一个方法一样,把一些变量的类型纠正为正确的数据型。

修改后的源代码:

void ZipReaderPrivate::scanFiles()

void ZipReaderPrivate::scanFiles()
{if (!dirtyFileTree)return;if (! (device->isOpen() || device->open(QIODevice::ReadOnly))) {status = ZipReader::FileOpenError;return;}if ((device->openMode() & QIODevice::ReadOnly) == 0) { // only read the index from readable files.status = ZipReader::FileReadError;return;}dirtyFileTree = false;uchar tmp[4];device->read((char *)tmp, 4);if (readUInt(tmp) != 0x04034b50) {qWarning("QZip: not a zip file!");return;}// find EndOfDirectory headerqint64 i = 0;uint start_of_directory = -1;ushort num_dir_entries = 0;EndOfDirectory eod;while (true) {const qint64 pos = device->size() - qint64(sizeof(EndOfDirectory)) - i;if (pos < 0 || i > 65535) {debugx("Zip: EndOfDirectory not found。 ");return;}device->seek(pos);device->read((char *)&eod, sizeof(EndOfDirectory));if (readUInt(eod.signature) == 0x06054b50)break;++i;}// have the eodstart_of_directory = readUInt(eod.dir_start_offset);num_dir_entries = readUShort(eod.num_dir_entries);debugx("start_of_directory at %u, num_dir_entries=%d", start_of_directory, num_dir_entries);int comment_length = readUShort(eod.comment_length);if (comment_length != i)debugx("QZip: failed to parse zip file.");comment = device->read(qMin(comment_length, i));device->seek(start_of_directory);for (i = 0; i < num_dir_entries; ++i) {FileHeader header;auto read = device->read((char *) &header.h, sizeof(CentralFileHeader));if (read < (qint64)sizeof(CentralFileHeader)) {debugx("QZip: Failed to read complete header, index may be incomplete,read:%lld,num_dir_entries:%d",read,num_dir_entries);break;}if (readUInt(header.h.signature) != 0x02014b50) {debugx("QZip: invalid header signature, index may be incomplete");break;}int l = readUShort(header.h.file_name_length);header.file_name = device->read(l);if (header.file_name.size() != l) {debugx("QZip: Failed to read filename from zip index, index may be incomplete");break;}l = readUShort(header.h.extra_field_length);header.extra_field = device->read(l);if (header.extra_field.size() != l) {debugx("QZip: Failed to read extra field in zip file, skipping file, index may be incomplete");break;}l = readUShort(header.h.file_comment_length);header.file_comment = device->read(l);if (header.file_comment.size() != l) {debugx("QZip: Failed to read read file comment, index may be incomplete");break;}//  debugx("found file '%s'", header.file_name.data());fileHeaders.append(header);}
}

QByteArray ZipReader::fileData(const QString &fileName)

QByteArray ZipReader::fileData(const QString &fileName) const
{d->scanFiles();int i;for (i = 0; i < d->fileHeaders.size(); ++i) {if (QString::fromLocal8Bit(d->fileHeaders.at(i).file_name) == fileName)break;}if (i == d->fileHeaders.size())return QByteArray();FileHeader header = d->fileHeaders.at(i);ushort version_needed = readUShort(header.h.version_needed);if (version_needed > ZIP_VERSION) {debugx("QZip: .ZIP specification version %d implementationis needed to extract the data.", version_needed);return QByteArray();}ushort general_purpose_bits = readUShort(header.h.general_purpose_bits);uint compressed_size = readUInt(header.h.compressed_size);uint uncompressed_size = readUInt(header.h.uncompressed_size);uint start = readUInt(header.h.offset_local_header);//qDebug("uncompressing file %d: local header at %d", i, start);d->device->seek(start);LocalFileHeader lh;d->device->read((char *)&lh, sizeof(LocalFileHeader));uint skip = readUShort(lh.file_name_length) + readUShort(lh.extra_field_length);d->device->seek(d->device->pos() + skip);ushort compression_method = readUShort(lh.compression_method);//qDebug("file=%s: compressed_size=%d, uncompressed_size=%d", fileName.toLocal8Bit().data(), compressed_size, uncompressed_size);if ((general_purpose_bits & Encrypted) != 0) {debugx("QZip: Unsupported encryption method is needed to extract the data.");return QByteArray();}//qDebug("file at %lld", d->device->pos());QByteArray compressed = d->device->read(compressed_size);if (compression_method == CompressionMethodStored) {// no compressioncompressed.truncate(uncompressed_size);return compressed;} else if (compression_method == CompressionMethodDeflated) {// Deflate//qDebug("compressed=%d", compressed.size());compressed.truncate(compressed_size);QByteArray baunzip;ulong len = qMax(uncompressed_size,  1u);int res;do {baunzip.resize(len);res = inflate((uchar*)baunzip.data(), &len,(const uchar*)compressed.constData(), compressed_size);switch (res) {case Z_OK:if ((int)len != baunzip.size())baunzip.resize(len);break;case Z_MEM_ERROR:debugx("QZip: Z_MEM_ERROR: Not enough memory");break;case Z_BUF_ERROR:len *= 2;break;case Z_DATA_ERROR:debugx("QZip: Z_DATA_ERROR: Input data is corrupted");break;}} while (res == Z_BUF_ERROR);return baunzip;}debugx("Zip: Unsupported compression method %d is needed to extract the data.", compression_method);return QByteArray();
}

调用示例:(功能,直接读取zip包里的指定的图像文件的内容)

Mat readImage(QString filePath,bool isZip, int flags)
{if(isZip){auto index= filePath.indexOf(".zip");QString zipFile=filePath.left(index+4);QString imgName=filePath.right(filePath.length()-index-5);//      debugx2(zipFile<<"\n"<<imgName);ZipReader zipreader(zipFile);for(auto fileInfo : zipreader.fileInfoList()){if(fileInfo.isFile){if(fileInfo.filePath==imgName){debugx2(fileInfo.filePath);//注意编码问题
//                    QByteArray dt = fileInfo.filePath.toUtf8();
//                    QString strtemp = QString::fromLocal8Bit(dt);QByteArray array = zipreader.fileData(fileInfo.filePath);//   debugx2(array.size());//   imshow("image",image);zipreader.close();if(array.size()>0)return  imdecode(std::vector<char>(array.constData(),array.constData()+array.size()),flags);else{debugx2(zipFile<<" read fail: "<<imgName);return Mat();}}}}zipreader.close();return Mat();}Mat src = cv::imread(filePath.toLocal8Bit().data(),flags);return src;
}

插件运行效果:不用解压zip,就可以直接浏览zip包里的图片。

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

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

相关文章

交通工程绪论

一、交通工程 交通工程学定义交通工程学研究的内容交通工程学的产生与发展交通工程学在道路运输管理中的作用 1. 交通工程学定义 早在20世纪30年代&#xff0c;美国交通工程师协会(American Institute of Traffic Engineers)给交通工程学(Traffic Engineering)下了一个定义&a…

每日一题 — 二分查找

704. 二分查找 - 力扣&#xff08;LeetCode&#xff09; 朴素二分查找模板&#xff1a; while(.......){//防止溢出int mid left(right - left)/2;if(........){right mid-1;}else if(......){left mid1;}else{return mid;}} 代码&#xff1a; public int search(int[] num…

jdbc操作数据库 and 一个商品管理页面

文章目录 1. 介绍1.1 应用知识介绍1.2 项目介绍 2. 文件目录2.1 目录2.2 介绍以下&#xff08;从上到下&#xff09; 3. 相关代码3.1 DBConnection.java3.2 MysqlUtil.java3.3 AddServlet.java3.4 CommodityServlet.java3.5 DelectServlet.java3.6 SelectByIdServlet.java3.7 S…

揭秘Faiss:大规模相似性搜索与聚类的技术神器深度解析!

Faiss&#xff08;由Facebook AI Research开发&#xff09;是一个用于高效相似性搜索和密集向量聚类的库。它用C编写&#xff0c;并提供Python绑定&#xff0c;旨在帮助研究人员和工程师在大规模数据集上进行快速的相似性搜索和聚类操作。 一、介绍&#xff1a; Faiss的核心功…

双链向表专题

1.链表的分类 链表的种类非常多组合起来就有 2 2 8种 链表说明&#xff1a; 虽然有这么多的链表的结构&#xff0c;但是我们实际中最常⽤还是两种结构&#xff1a; 单链表 和 双向带头循环链表 1. 无头单向⾮循环链表&#xff1a;结构简单&#xff0c;⼀般不会单独⽤来存数…

Ultralytics YOLOv8 英伟达™ Jetson®处理器部署

系列文章目录 前言 本综合指南提供了在英伟达 Jetson设备上部署Ultralytics YOLOv8 的详细攻略。此外&#xff0c;它还展示了性能基准&#xff0c;以证明YOLOv8 在这些小巧而功能强大的设备上的性能。 备注 本指南使用Seeed Studio reComputer J4012进行测试&#xff0c;它基于…

在邮件控件Aspose.Email中,处理Outlook TNEF 格式电子邮件

Microsoft Outlook 中常见的传输中性封装格式 (TNEF)电子邮件在处理和提取其内容时可能会带来挑战。在这篇博文中&#xff0c;我们将探讨如何使用强大的 .NET C# 库来处理此类消息&#xff0c;该库简化了各种电子邮件格式&#xff08;包括 TNEF&#xff09;的处理。 Aspose.Em…

尚硅谷-JavaSE阶段考试与面试题库

一、基础题 1&#xff09;用最有效的的方法算出2称以8等于几 答案&#xff1a;2<<3 2&#xff09;两个对象a和b&#xff0c;请问ab和a.equals(b)有什么区别&#xff1f; ab&#xff1a;比较对象地址 a.equals(b)&#xff1a;如果a对象没有重写过equals方法&#xff0c…

【技术干货】润石红外额温枪方案芯片功能介绍

手持红外额温枪框图中&#xff0c;以电池采用9V为例&#xff0c;先通过一个高压LDO RS3002 把电池电压转为3V&#xff0c;供整个系统使用&#xff0c;包括为 MCU&#xff0c;背光灯&#xff0c;运放 等器件供电&#xff0c;然后再用一个低功耗LDO RS3236 从3V 降为1.5V&#…

rc_visard 3D Stereo Senso

1 简介 rc_visard 3D立体视觉传感器 支持的接口标准 GenICam Generic Interface for CamerasGigE Gigabit Ethernet 词汇表 SGM semi-global matching 半全局匹配 SLAM Simultaneous Localization and Mapping 即时定位与地图构建 2 安全 3 硬件规格 坐标系 rc_visar…

TypeScript 中 interface 和 type 的使用#记录

一、interface&#xff1a;接口 interface A{label: string; }const aa ((aObj: A) > {console.log(aObj.label);//123return aObj.label; })aa({label: 123}) 1、可选属性 interface A{label: string;age?: number; } 2、只读属性 interface A{label: string;age?:…

231 基于matlab的北斗信号数据解析

基于matlab的北斗信号数据解析&#xff0c;多通道和单通道接收到的北斗信号数据&#xff0c;利用接收到的北斗数据&#xff08;.dat .txt文件&#xff09;&#xff0c;进行解析&#xff0c;得到初始伪距&#xff0c;平滑伪距&#xff0c;载波相位&#xff0c;并计算其标准差&am…

翱途开发平台新手上路-体验APP移动手机办公

O2OA(翱途)开发平台拥有配套的移动办公APP&#xff0c;支持IOS和安卓端&#xff0c;用户可在连接O2云之后&#xff0c;使用APP使用移动办公。移动办公APP开放源代码&#xff0c;不会产生任何费用。本篇主要简单讲述初如何完成服务器连接O2云&#xff0c;实现移动办公。 一、先决…

Barnes-Hut t-SNE:大规模数据的高效降维算法

在数据科学和分析中&#xff0c;理解高维数据集中的底层模式是至关重要的。t-SNE已成为高维数据可视化的有力工具。它通过将数据投射到一个较低维度的空间&#xff0c;提供了对数据结构的详细洞察。但是随着数据集的增长&#xff0c;标准的t-SNE算法在计算有些困难&#xff0c;…

什么是IoT?

什么是IoT&#xff1f; IoT&#xff0c;即物联网&#xff08;Internet of Things&#xff09;&#xff0c;是通过信息传感设备和互联网将各种物品连接起来&#xff0c;实现智能化的识别、定位、跟踪、监控和管理的网络系统。 以下是关于IOT的一些详细解释&#xff1a; 基本概…

JVM之本地方法栈和程序计数器和堆

本地方法栈 本地方法栈是为虚拟机执行本地方法时提供服务的 JNI&#xff1a;Java Native Interface&#xff0c;通过使用 Java 本地接口程序&#xff0c;可以确保代码在不同的平台上方便移植 不需要进行 GC&#xff0c;与虚拟机栈类似&#xff0c;也是线程私有的&#xff0c;…

OCP Java17 SE Developers 复习题13

答案 D, F. There is no such class within the Java API called ParallelStream, so options A and E are incorrect. The method defined in the Stream class to create a parallel stream from an existing stream is parallel(); therefore, option F is correct, and o…

高斯溅射融合之路(一)- webgl渲染3d gaussian splatting

大家好&#xff0c;我是山海鲸的技术负责人。之前已经写了一个GIS融合系列。其实CesiumJS的整合有相当的难度&#xff0c;同时也有很多方面的工作&#xff0c;很难在几篇文章内写完&#xff0c;整个山海鲸团队也是投入了接近两年的时间&#xff0c;才把周边整套工具链进行了完善…

Linux中inode号与日志分析

一.inode号 1.inode表结构 元信息&#xff1a;每个文件的属性信息&#xff0c;比如&#xff1a;文件的大小&#xff0c;时间&#xff0c;类型&#xff0c;权限等&#xff0c;称为文件的元数据(meta data 元信息 ) 元数据是存放在inode&#xff08;index node&#xff09;表中…

Spring Kafka—— KafkaListenerEndpointRegistry 隐式注册分析

由于我想在项目中实现基于 Spring kafka 动态连接 Kafka 服务&#xff0c;指定监听 Topic 并控制消费程序的启动和停止这样一个功能&#xff0c;所以就大概的了解了一下 Spring Kafka 的几个重要的类的概念&#xff0c;内容如下&#xff1a; ConsumerFactory 作用&#xff1a;…