解决Minizip压缩后解压时的头部错误问题
最近,在处理文件压缩的任务时,我遇到了一个有趣的问题。使用Minizip库进行文件压缩后,在解压过程中收到了一个关于"头部错误"的警告。尽管这个警告看似令人担忧,但解压操作最终仍然能够成功完成文件的解压。这引发了我的好奇心,我决定深入探究这个问题。
首先,想分享一下我使用的压缩代码:
bool XXXCompressor::compressData(const std::string &input_file_name, const std::string &output_file_name)
{// 打开ZIP文件,如果不存在则创建zipFile zf = zipOpen(output_file_name.c_str(), APPEND_STATUS_CREATE);if (zf == NULL){LOGE("Error opening ZIP file. output_file_name: %s", output_file_name.c_str());return false;}// 打开要压缩的文件FILE *file_to_zip = fopen(input_file_name.c_str(), "rb");if (!file_to_zip){LOGE("Error opening file to zip. input_file_name: %s", input_file_name.c_str());zipClose(zf, NULL);return false;}// 定义ZIP条目zip_fileinfo zfi;memset(&zfi, 0, sizeof(zfi));size_t found = input_file_name.find_last_of("/\\");std::string filename_zip;if (found != std::string::npos){filename_zip = input_file_name.substr(found + 1);filename_zip = filename_zip + ".log";}// 打开ZIP中的新文件条目if (zipOpenNewFileInZip(zf, filename_zip.c_str(), &zfi,NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK){LOGE("Error opening file in ZIP.");fclose(file_to_zip);zipClose(zf, NULL);return false;}// 读取文件内容并写入ZIP// char buffer[1024];memset(buffer, 0, sizeof(buffer));unsigned int len;while ((len = fread(buffer, 1, sizeof(buffer), file_to_zip)) > 0){if (zipWriteInFileInZip(zf, buffer, len) < 0){LOGE("Error writing file in ZIP.");break;}}// 关闭ZIP中的文件条目if (zipCloseFileInZip(zf) != ZIP_OK){LOGE("Error closing file in ZIP.");}// 关闭文件和ZIP文件fclose(file_to_zip);if (zipClose(zf, NULL) != 0){LOGE("Error closing ZIP file.");}return true; // 压缩成功
}
这段代码在压缩文件时表现良好,但在解压时却出现了一些不和谐的声音。如下图:

经过一系列的测试和研究,我发现这个“头部错误”的警告可能是由于Minizip在解压时对文件头部的某些预期与实际不符所导致的。 这种情况虽然并未影响到文件的最终解压结果,但它确实引起了我对压缩过程可靠性的疑虑。
为了解决这个问题,我查阅了Minizip的官方文档和社区讨论,寻找是否有其他用户遇到类似问题的解决方案。发现缺失了filetime操作,即:
#ifdef _WIN32
# include <direct.h>
# include <io.h>
#else
# include <unistd.h>
# include <utime.h>
# include <sys/types.h>
# include <sys/stat.h>
#endif#ifdef _WIN32#define USEWIN32IOAPI#include "iowin32.h"
#endif
#ifdef _WIN32
/* f: name of file to get info on, tmzip: return value: access,modification and creation times, dt: dostime */
static int filetime(const char *f, tm_zip *tmzip, uLong *dt) {(void)tmzip;int ret = 0;{FILETIME ftLocal;HANDLE hFind;WIN32_FIND_DATAA ff32;hFind = FindFirstFileA(f,&ff32);if (hFind != INVALID_HANDLE_VALUE){FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);FindClose(hFind);ret = 1;}}return ret;
}
#elif defined(__unix__) || defined(__unix) || defined(__APPLE__)
/* f: name of file to get info on, tmzip: return value: access,modification and creation times, dt: dostime */
static int filetime(const char *f, tm_zip *tmzip, uLong *dt) {(void)dt;int ret=0;struct stat s; /* results of stat() */struct tm* filedate;time_t tm_t=0;if (strcmp(f,"-")!=0){char name[MAXFILENAME+1];size_t len = strlen(f);if (len > MAXFILENAME)len = MAXFILENAME;strncpy(name, f,MAXFILENAME-1);/* strncpy doesn't append the trailing NULL, of the string is too long. */name[ MAXFILENAME ] = '\0';if (name[len - 1] == '/')name[len - 1] = '\0';/* not all systems allow stat'ing a file with / appended */if (stat(name,&s)==0){tm_t = s.st_mtime;ret = 1;}}filedate = localtime(&tm_t);tmzip->tm_sec = filedate->tm_sec;tmzip->tm_min = filedate->tm_min;tmzip->tm_hour = filedate->tm_hour;tmzip->tm_mday = filedate->tm_mday;tmzip->tm_mon = filedate->tm_mon ;tmzip->tm_year = filedate->tm_year;return ret;
}
#else
/* f: name of file to get info on, tmzip: return value: access,modification and creation times, dt: dostime */
static int filetime(const char *f, tm_zip *tmzip, uLong *dt) {(void)f;(void)tmzip;(void)dt;return 0;
}
#endif
之后将下面这行语句加入压缩前的代码中即可
filetime(filename_zip.c_str(),&zfi.tmz_date,&zfi.dosDate);
在接下来的段落中,我将详细分享我的解决方案和一些额外的心得体会,希望能帮助到遇到类似问题的朋友们。
相关文章:
解决Minizip压缩后解压时的头部错误问题
最近,在处理文件压缩的任务时,我遇到了一个有趣的问题。使用Minizip库进行文件压缩后,在解压过程中收到了一个关于"头部错误"的警告。尽管这个警告看似令人担忧,但解压操作最终仍然能够成功完成文件的解压。这引发了我的…...
数据库表水平分割和垂直分割?
0.数据库表的水平分割和垂直分割是两种常见的数据库优化技术,它们分别针对不同的场景和需求进行数据表的拆分。 1. 水平分割(Horizontal Splitting)主要是按照记录进行分割,即不同的记录被分开保存在不同的表中&#x…...
Linux源码阅读笔记18-插入模型及删除模块操作
基础知识 模块是一种向Linux内核添加设备驱动程序、文件系统及其他组件的有效方法,不需要编译新内核 优点 通过使用模块,内核发布者能够预先编译大量驱动程序,而不会致使内核映像的尺寸发生膨胀。内核开发者可以将实验性的代码打包到模块中&a…...
力扣面试经典算法150题:移除元素
移除元素 今日的题目依旧是力扣面试经典算法150题中数组相关的题目:移除元素 题目链接:https://leetcode.cn/problems/remove-element/description/?envTypestudy-plan-v2&envIdtop-interview-150 题目描述 给定一个排序数组 nums 和一个值 val&a…...
java关于前端传布尔值后端接收一直为false问题
前端传值: {"message":"我肚子疼","isChiefComplaint": true }后端接收对象结构体: public class SymptomInquiryDTO {private String message;private boolean isChiefComplaint; }结果后端接收到的值一直是false&…...
工具学习_CVE Binary Tool
1. 工具概述 CVE Binary Tool 是一个免费的开源工具,可帮助您使用国家漏洞数据库(NVD)常见漏洞和暴露(CVE)列表中的数据以及Redhat、开源漏洞数据库(OSV)、Gitlab咨询数据库(GAD&am…...
智观察 | 行业赛道里的AI大模型
“AI改变世界”被炒得热火朝天,结果就换来AI聊天? 实际上,在日常娱乐之下,AI正在暗暗“憋大招”,深入各行各业,发挥更专业的作用。 自动驾驶 最近“萝卜快跑”霸榜热搜长达一周,让无人驾…...
linux 进程 inode 信息获取
根据端口查找 ss -neltup | grep "$port"根据 pid 查找 ss -neltup | grep "pid$pid"根据 inode 查找 ss -neltup | grep "ino:$inode"根据pid查找进程打开的inode ls -al /proc/$pid/fd查看inode信息 cat /proc/$pid/net/tcp | grep $ino…...
计算机网络-网络层
负责在不同的网络之间转发数据包,基于数据包的 IP地址转发,每个数据包可以按照不同路径传输。网络层不负责丢包重传,以及数据包之间数据顺序的的问题。 网络设备 路由器工作在第三层:网络层,能看到网络层的地址&…...
机器学习:识别AI,GraphRAG,LoRA,线性变换,特征
1.AI识别 1.bitgrit 生成式 AI API 文档 生成式 AI 假图像检测 API 可用于以编程方式检测假图像(即由生成式 AI 创建的图像)。2.X Virality Prediction API 旨在预测推文的潜在病毒式传播力。https://bitgrit.net/api/docs/x_virality_prediction 2.Gr…...
阿里云SMS服务C++ SDK编译及调试关键点记录
一. 阿里云SMS服务开通及准备工作 在阿里云官网上完成这部分的工作 1. 申请资质 个人or企业 我这里是用的企业资质 2. 申请签名 企业资质认证成功后,会自动赠送一个用于测试的短信签名 也可以自己再进行申请,需要等待审核。 3. 申请短信模板 企…...
Flutter 正在迁移到 Swift Package Manager ,未来会弃用 CocoaPods 吗?
什么是 Swift Package Manager ?其实 Swift Package Manager (SwiftPM) 出现已经挺长一段时间了,我记得第一次听说 SwiftPM 的时候,应该还是在 2016 年,那时候 Swift 3 刚发布,不过正式出场应该还是在 2018 年的 Apple…...
PDF——分割pdf的10个工具
PDF分割器是一种可用于将PDF文档分割成更小的文档甚至单个页面的工具。分割 PDF 文档的主要原因是为了更容易共享。 但该过程的成功取决于您用于拆分 PDF 的工具。较简单的工具仅提供几个选项,可能并不适合所有类型的文档。我们将在本文中列出的 10 个最佳 PDF 分割…...
深入解析 Nginx 反向代理:配置、优化与故障排除
深入解析 Nginx 反向代理:配置、优化与故障排除 Nginx 是一个高性能的 HTTP 和反向代理服务器,它以其高并发和高可扩展性在业界享有盛誉。反向代理是 Nginx 的重要功能之一,通过反向代理可以实现负载均衡、安全代理、缓存等多种用途。本篇文…...
深度学习入门(一):感知机与输入数据
单层感知机与多层感知机 单层感知机(Single-Layer Perceptron)和多层感知机(Multi-Layer Perceptron,简称MLP)是神经网络的基本形式,用于执行各种机器学习任务,包括分类和回归。它们都基于早期…...
kubernetes 集群组件介绍
kubernetes 集群组件介绍 Kubernetes 架构 在Kubernetes(k8s)集群中,主节点(Master Node)和工作节点(Worker Node)都运行特定的软件组件,它们共同管理和运行容器化的应用程序。以下…...
Java | Leetcode Java题解之第327题区间和的个数
题目: 题解: class Solution {public int countRangeSum(int[] nums, int lower, int upper) {long sum 0;long[] preSum new long[nums.length 1];for (int i 0; i < nums.length; i) {sum nums[i];preSum[i 1] sum;}BalancedTree treap ne…...
开发一个MutatingWebhook
介绍 Webhook就是一种HTTP回调,用于在某种情况下执行某些动作,Webhook不是K8S独有的,很多场景下都可以进行Webhook,比如在提交完代码后调用一个Webhook自动构建docker镜像 准入 Webhook 是一种用于接收准入请求并对其进行处理的…...
【leetcode详解】另一棵树的子树 (C++递归:思路精析 过程反思)
思路详解: 总体框架: 对root树进行先序遍历,如果当前结点(记为cur)的值和subRoot的根节点值相等时,就开始判断 以cur为根节点的树 和 子树 是否结构一样? 如何判断两棵树是否结构完全相同? …...
物联网遇到人工智能,极快的加速物联网时代
近些年物联网已成为众多科技企业的战略目标,如智能家居等,在未来,手机、传感器等智能设备都走进了生活当中,据数据显示已经有80%以上的的智能手机配备了人工智能。人工智能也不陌生,自动驾驶、人脸识别这些应用场景都是…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
