总体结构

总体结构

我有 4 个问题:

  1. 是否可以扫描整个 zip 文件并在其中导航而无需使用 PHP 提取整个 zip?
  2. 这会节省时间吗?例如,我有一个大约 50GB 的 zip 文件,其中包含许多小文件(特别是过去的大量图像),我想使用 PHP 制作一个文件资源管理器。
  3. 这可以递归完成吗?也就是说,如果我在一个大 zip 包里有很多 zip 包,我能解析它们吗?
  4. 如果我可以解析 zip 文件,那么是否意味着我可以像在普通文件浏览器中一样打开里面的文件?

答案1

可能吧。简单谷歌搜索一下,结果显示。看起来它完全支持 Zip 档案。

答案2

全部是。至少如果“扫描整个 zip 文件”并不意味着真正扫描整个文件。如果文件较小,则无所谓,但如果文件较大,则需要扫描。

简而言之,ZIP 文件的构建方式使得无需读取整个文件即可列出、更新、删除和添加文件。另请注意,最初 ZIP 通常用于保存可能跨多个磁盘的磁盘。换句话说,您可以拥有一个从磁盘 #1 开始到磁盘 #44 结束的 zip 文件。

如果文件位于一个磁盘上,则无需磁盘#1 - 磁盘#28 即可提取磁盘#29 上的文件 342,这一事实也适用,但从概念上讲,这可能更容易理解。您无需读取文件#1 到文件#341 即可提取文件#342。

除此之外,简而言之,ZIP 档案以中央目录结束。此目录包含有关 zip 档案的当前状态以及应使用的信息。


总体结构

zip 档案的整体结构通常如下(简化):

Local File Header 1
      File Data   1
      Descriptor  1 (optional) 
Local File Header 2
      File Data   2
      Descriptor  2 (optional)
Local File Header N
      File Data   N
      Descriptor  N (optional)

Central Directory
   Details File 1
   Details File 2
   Details File N
   End Of Central Directory

但是 ZIP 档案“允许”对于非档案数据以及删除和添加条目(不需要删除数据)。

Allow 在这里使用得相当灵活

因此档案可能是这样的:

Local File Header 1
      File Data   1
Local File Header 2
      File Data   2
Non Archive Data    << not part of the archive, but part of the file.
Local File Header 3
      File Data   3
      Descriptor  3
Non Archive Data    << not part of the archive, but part of the file.
Central Directory   << old central directory
   Details File 1
   Details File 2
   End Of Central Directory

Local File Header 4
      File Data   4

Central Directory
   Details File 1
   Details File 3
   Details File 4
   End Of Central Directory

这里有一种场景,在某些记录之间添加了数据,文件 2 已被删除,但数据未被删除,文件 4 已被添加,并且写入了新的中央目录而没有删除旧的。

事实上,我们可以将 zip 存档附加到任何现有文件,并且它仍然可用。

foo.zip
[GIF IMAGE]
[ZIP FILE RECORD]
[LETTER TO MOM]
[ZIP FILE RECORD]
[CENTRAL DIRECTORY]

有人可能会说这个文件乱七八糟,但作为 ZIP 存档,它还是可以读取的。有人可能会说它不符合规范,并愿意忽略它,但那是另一回事。

重点是:

合适的 ZIP 阅读器使用最后一个中央目录。该目录应始终保存有关档案当前状态的信息。它提供有关文件名、时间、日期、压缩方法、磁盘起始、磁盘结束、文件数、每个文件的起始和结束位置、每个文件的校验和等信息。

人们可以将 zip 档案看作一个巨大的数据块,其中 CD 标明了每个文件的开始和结束位置++。


一般来说

大多数 zip 档案当然比这个干净得多,但只能提供一点背景信息。

简而言之:要概览档案中的文件,只需阅读 CD。通过这种方式可以列出例如:

file1 date size_compressed size_uncompressed
file2 date size_compressed size_uncompressed
file3 date size_compressed size_uncompressed
file4 date size_compressed size_uncompressed

本地文件头在恢复损坏的文件或 CD 丢失等情况下很有用,但也可能缺失。它通常保存文件数据的大小,但并非总是如此。如果没有,通常是

Local File Header
  ...
  size_compressed: 0
  size_uncompressed: 0
  ...
File Data
Descriptor
   size_compressed: 3214
   size_uncompressed: 6128

因此,如果您从字节 0 读取文件,您最终会遇到这样的问题:必须猜测数据从哪里开始和结束。

一个典型的原因是 ZIP 可以存档数据流。因此,在写入文件之前,人们不知道文件的大小,也不知道校验和,因此文件头无法保存这些信息。这里还要记住,一个文件可以跨多个磁盘。但是,大小应始终添加到 CD 中。


由于可以读取文件的开始和结束位置,因此挑选文件也很容易。如果 CD 表示文件从偏移量 632156 开始,到偏移量 952144 结束,则读取这些字节,如果已压缩,则相应地解压缩。

如果有嵌套文件、档案内有档案、档案内有档案等,则需要查找每个档案各自的 CD 解析。

边注:简单的当然是相对的。

中央目录记录结束

正如档案可以跨多个磁盘一样,CD 也可以跨多个磁盘。中央目录记录结束保存了 CD 从哪个磁盘开始和结束的信息。如今,通常是同一个磁盘,但这是一个重要的提示,如果决定从规格来看格式,则更容易理解。

当然,还有很多其他内容。这完全取决于用户想要支持什么。例如,数据是否可以加密。

如需完整阅读,请查看APP注释.TXT

了解 ZIP 存档构建的基本原理,可以让您更轻松地知道在使用 PHP Zip 等库时可以做什么和不能做什么。


PHP 压缩文件

从未使用过它,但从外观上看,它具有您需要的所有功能。猜测除非被询问,否则它不会读取文件数据。例如,请看此处的示例 2:https://www.php.net/manual/en/zip.examples.php

在大型档案上进行测试并计时。如果它只读取 CD,那么即使是读取大型档案也应该相对较快。


曾经为了好玩而编写过一个 ZIP 解析器,但那完全是另一回事哈哈。

相关内容