解决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);

在接下来的段落中,我将详细分享我的解决方案和一些额外的心得体会,希望能帮助到遇到类似问题的朋友们。

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

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

相关文章

BM1反转链表[栈+头插法]

题目要求如下: 问题比较简单,就是将链表中的值进行反转即可。 一种比较简单的方式是使用栈链表的方式来实现,下面是相应的代码: #include <stdio.h> #include <stdlib.h> int arr[10001] {0}; struct ListNode* ReverseList(struct ListNode* head ) {if (head …

编译运行 Byconity

我的系统是centos&#xff0c;因此用他们的docker编译并用他们的docker-compose运行&#xff0c;以下流程亲测可跑&#xff1a; 拉取并编译 https://github.com/ByConity/ByConity/tree/master/docker/debian/dev-env 运行 https://github.com/ByConity/ByConity/blob/master/d…

Day-16 SpringBoot原理

SpingBoot原理 在前面十多天的课程当中&#xff0c;我们学习的都是web开发的技术使用&#xff0c;都是面向应用层面的&#xff0c;我们学会了怎么样去用。而我们今天所要学习的是web后端开发的最后一个篇章springboot原理篇&#xff0c;主要偏向于底层原理。 我们今天的课程安…

20240807 每日AI必读资讯

&#x1f468;‍&#x1f4bc;马斯克再发难、OpenAI 高层巨变&#xff1a;两大核心人物离职&#xff0c;总裁休长假到年底 - OpenAI 联合创始人 John Schulman 官宣离职&#xff0c;加入原是竞品公司的 Anthropic - 陪伴 OpenAI 共同成长 9 年的总裁兼联合创始人 Greg Brockm…

事务和索引(面试常问)

面试常问&#xff1a; 一、数据库隔离级别&#xff1f;事务隔离级别解决的问题&#xff1f; 答&#xff1a;1.数据库隔离级别&#xff1a; READ_UNCOMMITTED 读未提交 READ_COMMITTED 读提交&#xff08;不可重复读&#xff09; REPEATABLE_READ 可重复读 SERIALIZABLE 串行化…

sed 简易使用指南

sed 简易使用指南 1 sed 介绍2 查找3 替换4 反向引用5 删除6 cai&#xff08;菜&#xff09; 导言&#xff1a; 笔者之前花了较多时间学习并整理了sed命令相关的内容&#xff0c;以及一些进阶内容。但是&#xff0c;到后来使用也就只记得那么几个简单的选项&#xff0c;再高级的…

6-8 残差网络(ResNet)

随着我们设计越来越深的网络&#xff0c;深刻理解“新添加的层如何提升神经网络的性能”变得至关重要。更重要的是设计网络的能力&#xff0c;在这种网络中&#xff0c;添加层会使网络更具表现力&#xff0c; 为了取得质的突破&#xff0c;我们需要一些数学基础知识。 残差网络…

【虚拟化】KVM使用virt-manager部署及管理虚拟机

目录 一、KVM 概述 二、KVM工作原理 三、部署KVM 四、新建虚拟机步骤 4.1 创建存储池并创建存储卷 4.1.1 创建存储池 4.1.2 创建存储卷 4.3 创建ISO存储池 4.4 生成新的虚拟机 一、KVM 概述 KVM 是 Kernel-based Virtual Machine 的缩写&#xff0c;是一种用于虚拟化的…

大模型微调深入研究

在本博文系列的前一部分中&#xff0c;我们探讨了情境学习的概念&#xff0c;这是一种克服大型语言模型 (LLM) 的“舒适区”限制的强大方法。我们讨论了如何使用这些技术来转换任务并将其移回模型的专业领域&#xff0c;从而提高性能并与有用性、诚实性和无害性的关键设计原则保…

WebBench源码分析

WebBench 源码解析 一、前言 WebBench 作为一款网站性能测试工具&#xff0c;其源码蕴含着丰富的技术细节和逻辑流程。本文将深入剖析其安装编译过程以及关键函数的核心逻辑。 二、安装编译 1. 克隆代码到本地仓库 git clone https://github.com/EZLippi/WebBench.git2. 编…

使用 Squid 搭建 Http 代理服务器隐藏 IP

在一些情况下&#xff0c;需要变更自己的访问 IP&#xff0c;可以通过 Squid 搭建代理服务器实现。 本文使用的是 CentOS 7.6 系统。 一、部署 Squid 安装 Squid。 yum install squid -y启动服 systemctl start squid二、访问控制 总有刁民想害郑&#xff0c;疯狂访问朕的…

基于宝塔面板稳定快速安装 ssl 证书脚本

背景 我通过AI制作了不少关于签发ssl证书的脚本&#xff0c;目的是方便无脑安装&#xff0c;不需要懂代码。 但全都是基于acme.sh这个工具来设计的脚本&#xff0c;而且证书申请有点慢&#xff0c;有时还会申请失败。 然后我发现了certbot, 安装证书可谓神速&#xff01; c…

ASP.NET Core基础 - 简介

目录 一. 简介 A、跨平台性 B、高性能 C、开源性 D、模块化与可扩展性 E、集成现代前端技术 二. ASP.NET 4.x 和 ASP.NET Core 比较 A、架构与平台支持 B、性能 C、开发体验 D、社区支持与生态系统 三. NET 与 .NET Framework 比较 A、概念范围 B、跨平台能力 C…

基于JAVA的高考智能排考场系统设计与实现,源码、部署+讲解

绪 论 随着教育规模的不断扩大和技术的进步&#xff0c;传统的考试管理方式面临着诸多挑战&#xff0c;如考试安排的复杂性、作弊现象的频发以及考试过程中的监督和管理等问题。因此&#xff0c;针对这些挑战&#xff0c;智能排考系统应运而生。 智能排考系统利用先进的技术…

数据结构(邓俊辉)学习笔记】词典 03—— 排解冲突(1)

文章目录 1. 一山二虎2. 泾渭分明3. 开放定址4. 线性试探5. 赖惰删除 1. 一山二虎 此前我们已经多次指出&#xff0c;对于需要动态维护的散列表冲突是不可避免的&#xff0c;无论你的散列函数设计的有多么精妙&#xff0c;因此我们不得不回答的第二个重要问题就是一旦发生冲突&…

零售EDI:OBI欧倍德EDI项目案例

OBI欧倍德公司是德国建材和家居装饰零售连锁店&#xff0c;在德国以及其他欧洲国家拥有众多分店&#xff0c;是欧洲领先的DIY&#xff08;Do It Yourself&#xff09;零售商之一。为了更好地处理与全球供应商之间的业务数据往来&#xff0c;OBI采用EDI提高其供应链的自动化水平…

基于微信小程序的宠物服务平台(系统源码+lw+部署文档+讲解等)

文章目录 目录 详细视频演示 系统详细设计截图 微信小程序系统的实现 1.1系统前台功能的实现 2.1微信小程序开发环境搭建 2.2微信开发者工具 2.3程序应用相关技术和知识 2.3.1小程序目录结构以及框架介绍 2.3.2 Java技术 2.3.3 MySQL数据库 2.3.4 SSM框架 源码获…

Pygame制作简单的跑酷游戏

今天我们来看看如何使用Pygame框架制作一个简单的跑酷游戏。这个游戏包含了基本的游戏元素,如玩家角色、障碍物、背景、音效等,可以作为入门Pygame游戏开发的一个不错的示例。 游戏概述 这是一个简单的横版跑酷游戏,玩家控制一个忍者角色,通过跳跃来躲避迎面而来的各种障碍物…

【研发日记】嵌入式处理器技能解锁(二)——TI C2000 DSP的SCI(串口)通信

文章目录 前言 背景介绍 SCI通信 Transmitter Receiver SCI中断 分析和应用 总结 参考资料 前言 见《【研发日记】嵌入式处理器技能解锁(一)——多任务异步执行调度的三种方法》 背景介绍 近期使用TI C2000 DSP做的一个嵌入式系统开发项目中&#xff0c;在使用它的SCI&…

Pytorch系列-张量的类型转换

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 张量转换为NumPy数组 使用Tensor.numpy()函数可以将张量转换为ndarray数组 # 1.将张量转换为numpy数组 data_tensortorch.tensor([2,3,4]) # 使用张量对象中的numpy函数进行转…