当前位置: 首页 > news >正文

Magicodes.IE.IO:XLSX 包结构:ZIP、关系文件与顺序写入

XLSX 是一组有关系约束的 ZIP 部件。导出要在不能回写的输出流上写 Local Header、Data Descriptor 和 Central Directory;导入则要从工作簿关系(workbook relationship)找到真正的工作表。本文把两条路径放在同一个包结构里解释。

XLSX 不是“一个 XML 文件”,而是一个 ZIP 包:

[Content_Types].xml
_rels/.rels
xl/workbook.xml
xl/_rels/workbook.xml.rels
xl/worksheets/...
xl/styles.xml
xl/sharedStrings.xml(可选)

导出和导入面对的是同一个包,只是方向相反:

导出:对象 → XML part → ZIP entry → 输出流
导入:输入流 → ZIP entry → XML part → 对象

导出:为什么要支持顺序写

HTTP 响应流通常不支持 Seek。写一个 ZIP entry 时,Local Header 在数据之前,但 CRC、压缩后尺寸和未压缩尺寸要等数据写完才知道。

ZIP 的 Data Descriptor 允许 Local Header 先把这些字段留空:

Local Header(CRC / size = 0)
压缩数据
Data Descriptor(真实 CRC / size)

ForwardOnlyZipWriter 用这个机制写 entry。entry 完成后,再把已经得到的 CRC、尺寸和偏移保存为 Central Directory 元数据;所有 entry 完成后,统一在文件尾写 Central Directory。

ZIP Entry 的数据流

一条 entry 的数据流是:

业务 XML 字节↓
EntryWriteStream├─ 统计未压缩大小├─ 更新未压缩数据的 CRC32↓
ICompressor / DeflateStream↓
CountingWriteStream├─ 统计压缩后大小↓
底层输出流

这不是“任意几层 Stream 都能随便拼”的模式演示。CRC、压缩、计数和 Data Descriptor 共享 entry 生命周期:压缩器必须 Finish,才能得到最终压缩尺寸;Data Descriptor 必须在尺寸和 CRC 确定后写入。

导入:不能假设第一个工作表叫 sheet1.xml

读取时,最简单的实现会直接打开:

xl/worksheets/sheet1.xml

外部工具生成的工作簿不保证这个路径就是逻辑上的第一个 sheet。Reader 当前读取第一个可读 worksheet,定位路径来自:

xl/workbook.xml↓ sheet 的 r:id
xl/_rels/workbook.xml.rels↓ Relationship.Target
xl/worksheets/实际文件.xml

XlsxReader 先根据工作簿关系(workbook relationship)找第一个可读 worksheet;关系文件缺失时,才回退到 worksheets 目录中的 XML entry。这让 Reader 能处理工作表路径不按默认命名的 XLSX。

同一个边界,读写两边都要守

约束 导出侧 导入侧
关系文件 写出 workbook 与各 part 的关系 根据关系定位 worksheet
Shared Strings 最后写出 sharedStrings.xml 初始化时加载 sharedStrings.xml
ZIP 顺序 Data Descriptor + Central Directory ZipArchive 打开现有包
流所有权 Write(Stream, ...) 由调用方释放 Read(Stream, ...) 默认在枚举结束时关闭

ZIP32 的范围

当前 writer 不支持 ZIP64。单个 entry、归档偏移和 Central Directory 尺寸受 ZIP32 的 32 位字段限制;entry 数量和名称长度还有 16 位字段限制。超过限制时应拆分文件、拆分 sheet,或改用支持 ZIP64 的方案。

http://www.jsqmd.com/news/1289620/

相关文章:

  • 2026年交通标志牌制造领域的关键能力维度与供应体系观察 - 优企名品
  • 华庆包装:全程真空吸附印刷模切机专属技术解决方案,数码印刷机/印刷粘箱联动线,全程真空吸附印刷模切机直销厂家口碑推荐 - 品牌推荐师
  • 好用的远程桌面软件怎么选 优质的远程桌面软件推荐
  • 2026 年主流 AI 修图工具测评!ImageGood 领衔,新手零基础修图全覆盖 - 米諾
  • 【Linux】Linux 系统负载查看与瓶颈判断运维手册
  • 10分钟部署Metasploitable2靶场:国内镜像加速与SSH免密登录实战
  • Fang实战案例:构建高可用的Rust后台任务处理系统
  • iDRAC-Redfish-Scripting与SCP功能结合:服务器配置文件导入导出全流程
  • Get It.本地数据安全指南:你的学习资料如何得到全面保护
  • Bootstrap for Ember.js面板组件教程:打造精美内容展示区域
  • 电动机降压启动技术解析与应用实践
  • 南昌举办生日宴的火锅店推荐|多场景适配本地觅食实用指南 - 品牌2026推荐
  • 全球EMBA特色择校指南,民营企业家怎么选更适配
  • Path of Building PoE2:终极流放之路2角色构建规划器完全指南
  • Lix持久化机制解析:如何确保你的数据在频繁修改中安全可靠?
  • Sharp-dumpkey终极指南:3分钟快速获取微信数据库密钥的免费工具
  • 2026上海日本留学机构哪家好 实力品牌盘点 - 谁都没有我好看
  • Tanel Poder的TPT-Oracle高级技巧:DBA必备的性能调优秘籍
  • 南昌排队王火锅店觅食指南:覆盖全场景的本地火锅打卡盘点 - 品牌2026推荐
  • 2026年大庆汽车贴膜选店指南:结合本地气候的选店标准与门店参考 - 米諾
  • 一键备份QQ空间:GetQzonehistory终极记忆守护者
  • AM64x硬件防火墙实战:从寄存器解析到内存保护配置
  • OpenMCP插件 vs Web vs App:三种部署模式优缺点对比
  • 2026客服Agent产品推荐:实测后总结了这份选型清单 - 2027品牌AI展
  • 人工智能国际EMBA择校指南,企业家进阶怎么选
  • 2026年甄选:仓储仓库地坪施工领域具备专业实力的服务公司解析 - 优企名品
  • SPARTA空间音频插件对比:为什么它比传统音频工具更胜一筹?
  • 数据库分库分表实践:tech-pdai-spring-demos中的Sharding-JDBC配置指南
  • Luckysheet 内网部署教程:后端生成 Excel,前端只读预览
  • AI Agent 开发实战(六):用 Spring AI 搭建你的第一个 Agent