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,一经查实,立即删除!

相关文章

Vue 常用修饰符

目录 定义 事件修饰符 v-on&#xff08;缩写&#xff09; 鼠标按键修饰符 v-bind 修饰符&#xff08;缩写:&#xff09; 键值修饰符 表单修饰符 定义 修饰符是用于限定类型以及类型成员的声明的一种符号&#xff0c;vue 中修饰符分为以下五种&#xff1a;事件修饰符、鼠…

网络通信 mac表 tcp连接

多台设备连接到集线器上通过mac地址广播通信 设备连接到交换机上&#xff0c;交换机记录mac表&#xff0c;就不需要广播了&#xff0c;但是机器增多就不行了&#xff0c;交换机只关注mac地址 多台设备连接到交换机上&#xff0c;不同局域网的设备要通信&#xff0c;就把多个交…

交通工程绪论

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

转:Learn Rust the Dangerous Way-系列文章翻译-总述

原文地址 太精彩了&#xff0c;不转不足以表达我的喜爱。 前言 《Learn Rust the Dangerous Way》​cliffle.com/p/dangerust/ 最近发现了一个学习Rust的优秀系列文章&#xff0c;本人准备对该系列文章进行翻译。 本文是《Learn Rust the Dangerous Way》系列文章翻译的第…

每日一题 — 二分查找

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&#…

c++ 泛型的赋值运算符怎么写 简单实验

1.概要 1.泛型的赋值运算符怎么写 A operator(const A& a) A<T> operator(const A<T>& a) 那个是正确的呢&#xff1f; 结果&#xff1a;都可以&#xff0c;但是不能重复 2.代码 #include <iostream> using namespace std;class B { public:B ope…

C++设计模式探讨(2)-单例模式

介绍 这段介绍来自网络&#xff1a; 单例模式是一种创建型的软件设计模式&#xff0c;在工程项目中非常常见。通过单例模式的设计&#xff0c;使得创建的类在当前进程中只有一个实例&#xff0c;并提供一个全局性的访问点&#xff0c;这样可以规避因频繁创建对象而导致的内存…

Go语言第二篇-基本数据类型与转义字符

-———————————————————————————— 随便记录没什么顺序&#xff1a; ———————————————————————————— &#x1f523;本部分内容记录了以下知识点&#xff1a; &#x1f30f;转义字符的使用 &#x1f30f;基本数据类型的使…

node項目的开发

01 创建package.json文件&#xff1a; npm init 创建一个package.json 项目描述的文件。package name &#xff1a; 包名version&#xff1a;版本description&#xff1a;项目描述entry point&#xff1a;入口文件 默认index.jstset command&#xff1a;测试命名git reposito…

协程/线程/进程的简单应用

使用FastApi模拟网络IO接口 import timefrom fastapi import FastAPIapp FastAPI()# 文件名 api.py # 运行: uvicorn api:app --reloadapp.get("/sleep/{times}") def sleep(times: int):# 模拟接口耗时time.sleep(times)return {"sleep": times}async…

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…