当前位置:首页 > 文章列表 > Golang > Go教程 > Go archive/zip 如何只读取压缩包中央目录信息

Go archive/zip 如何只读取压缩包中央目录信息

来源:17golang原创 2026-09-12 19:01:43 0浏览 收藏

如果任务只是列出 ZIP 里有哪些文件、判断大小或找出某个扩展名,没必要把每个条目的正文都解压出来。Go 的 archive/zip 已经把中央目录解析成 Reader.File,遍历它就能拿到 FileHeader 中的元信息;只有命中目标后,才调用 File.Open 读取正文。

要点速览
  • zip.OpenReaderzip.NewReader 会建立 ZIP Reader,清单在 Reader.File
  • FileHeader 适合读取名称、目录标识、压缩方式、压缩前后大小和修改时间。
  • 筛选元数据时不要调用 File.Open;正文读取要检查错误并关闭返回的流。

读取中央目录就能完成大多数清单任务

ZIP 的中央目录保存了每个条目的名称、压缩方式、压缩大小、原始大小、CRC 和修改时间等字段。archive/zip 的 Reader 初始化时会定位并解析这部分目录,所以清单阶段可以只遍历 r.File,并不会因为读取 f.Name 就展开文件正文。

本地 ZIP 文件使用 OpenReader 最直接;输入已经在内存或实现了随机读取时,则用 NewReader,同时传入准确的字节数:

package main

import (
	"archive/zip"
	"fmt"
	"log"
)

func main() {
	// OpenReader 负责打开文件并解析 ZIP 的中央目录。
	r, err := zip.OpenReader("assets.zip")
	if err != nil {
		log.Fatal(err)
	}
	defer r.Close() // ReadCloser 持有底层文件句柄,函数结束时释放。

	for _, f := range r.File {
		// 这里只访问清单对象,不调用 f.Open() 读取压缩正文。
		fmt.Println(f.Name)
	}
}
Go archive/zip 中 zip.OpenReader、中央目录、Reader.File 与 FileHeader 的静态关系示意
图1:中央目录解析后形成 Reader.File 清单;遍历元数据不等于打开条目正文的结构示意图。

这里的“只读取”是业务层面的读取边界:程序仍需从 ZIP 尾部定位中央目录并解析目录记录,但不会启动条目解压。目录损坏、文件不是合法 ZIP 或路径安全检查失败时,Reader 初始化仍可能返回错误。

从 FileHeader 提取条目元信息

zip.File 嵌入了 FileHeader,因此可以直接读取字段。清单程序通常先排除目录,再用 64 位大小字段做配额判断,避免旧的 32 位字段在大文件上溢出或显示为截断值。

字段用途判断提示
Name条目路径和文件名/ 结尾通常表示目录
Method压缩方式可用于显示或策略筛选,不代表正文已读取
CompressedSize64压缩后大小估算归档占用
UncompressedSize64解压后大小做展开前的容量检查
Modified条目修改时间用于清单展示或排序
for _, f := range r.File {
	// 目录也会出现在清单中,先排除再统计文件条目。
	if f.FileInfo().IsDir() {
		continue
	}
	// 64 位字段适用于大于 4 GiB 的条目,避免依赖旧字段。
	fmt.Printf("%s method=%d compressed=%d raw=%d modified=%s\n",
		f.Name, f.Method, f.CompressedSize64, f.UncompressedSize64,
		f.Modified.Format(time.RFC3339))
}

上面的片段需要额外导入 time。如果只做目录清单,也可以省略时间格式化。不要把 UncompressedSize64 当成已经分配的内存,它只是目录里声明的大小,真正展开前仍应设置自己的容量上限。

只有命中目标后才打开条目正文

元数据筛选和正文读取最好分成两个阶段。f.Open() 返回 io.ReadCloser,之后读取才会经过对应的解压器,并在读取过程中承担校验职责。若只是判断名称,调用它反而会增加 I/O 和 CPU 成本。

import (
	"io"
	"strings"
)

func readManifest(r *zip.Reader) ([]byte, error) {
	for _, f := range r.File {
		// 先用中央目录筛选目标,其他条目完全不打开。
		if f.Name != "manifest.json" || strings.HasSuffix(f.Name, "/") {
			continue
		}
		// 命中后才取得正文流,并确保所有返回路径都关闭它。
		rc, err := f.Open()
		if err != nil {
			return nil, err
		}
		body, readErr := io.ReadAll(rc)
		closeErr := rc.Close()
		if readErr != nil {
			return nil, readErr
		}
		if closeErr != nil {
			return nil, closeErr
		}
		return body, nil
	}
	return nil, fmt.Errorf("manifest.json not found")
}
Go archive/zip 从 zip.File 元数据筛选到 File.Open、io.ReadCloser、解压器和 CRC 校验的静态关系示意
图2:先在 FileHeader 层筛选,命中条目后才进入 File.Open 和正文流;这是元数据与内容读取的边界示意图。

输入来源和安全边界要提前分清

文件路径、*os.File 或内存字节都必须支持随机读取,才能让 Reader 按目录偏移访问 ZIP。只有顺序到来的网络流并不适合直接套 NewReader;应先落盘、缓存到支持 io.ReaderAt 的对象,或选择专门的流式格式。

另外,当前 Go 的 OpenReaderNewReader 可能因为条目名称包含反斜杠或非本地路径返回 zip.ErrInsecurePath。即使只看中央目录,也应把它当作输入检查结果处理;不要把所有错误都改成“忽略后继续”。

任务推荐动作不要做什么
列出条目遍历 Reader.File为每个条目调用 Open
检查展开风险比较 UncompressedSize64 与业务上限仅相信压缩后大小
读取一个文件名称命中后再 File.Open把目录字段当正文
处理外部 ZIP处理 ErrFormatErrInsecurePath无条件解压到目标目录

常见问题

遍历 r.File 会不会自动解压?

不会。遍历主要访问已解析的中央目录记录;真正读取条目内容通常从调用 File.Open 并读取返回流开始。

为什么 NewReader 还要传 size?

ZIP 的目录位置需要结合数据范围定位,NewReader 接收的是支持随机读取的对象和它的准确字节数。

只看大小就能保证解压安全吗?

不能。大小只能帮助限制容量,路径仍要检查,解压时还要限制输出、拒绝不安全名称并处理格式与校验错误。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Python tarfile 解压时如何检查成员路径Python tarfile 解压时如何检查成员路径
上一篇
Python tarfile 解压时如何检查成员路径
运营第一次用Lovart做活动主视觉,如何把需求表变成可审核素材?
下一篇
运营第一次用Lovart做活动主视觉,如何把需求表变成可审核素材?
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    105次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    21次使用
  • OpenCompass大模型评测体系详解:功能、使用指南与应用场景
    OpenCompass
    OpenCompass是上海AI实验室推出的开源大模型评测平台,提供CompassKit、CompassHub和CompassRank三大核心组件,支持LLM及多模态模型的一站式标准化评估与排行榜查询。
    31次使用
  • AGI-Eval大模型评测平台:权威榜单、数据集与人机协同评测方案
    AGI-Eval
    AGI-Eval是由上海交大等高校联合发布的大模型评测社区,提供公正透明的LLM能力榜单、多领域评测集及Data Studio数据服务,助力AI模型性能评估与NLP科研开发。
    22次使用
  • SuperCLUE中文大模型评测基准:功能、能力维度与应用指南
    SuperCLUE
    SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
    259次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码