假设有一个巨大db.sql.gz
的 100GB 可用https://example.com/db/backups/db.sql.gz
并且服务器支持范围请求。
因此,我没有下载整个文件,而是下载了y
带有字节偏移量(比如说 1000 字节)的x
字节(比如说 1024 字节),如下所示。
curl -r 1000-2024 https://example.com/db/backups/db.sql.gz
使用上述命令,我能够下载 gzip 文件的部分内容,现在我的问题是如何读取该部分内容?
我试过gunzip -c db.sql.gz | dd ibs=1024 skip=0 count=1 > o.sql
了,但这给出了一个错误
gzip:dbrange.sql.gz:不是 gzip 格式
该错误是可以接受的,因为我猜在文件的顶部可能有描述编码的标题块。
我注意到,如果我下载没有偏移量的文件,我可以使用gunzip
和管道读取文件。
curl -r 0-2024 https://example.com/db/backups/db.sql.gz
gzip
不生成块压缩文件(有关血腥细节,请参阅RFC),因此它本身不适合随机访问。您可以从流中开始读取并随时停止,这就是您的curl -r 0-2024
示例有效的原因,但您不能在中间选择流,除非您有一个补充文件来提供丢失的数据(例如索引文件由gztool
) 创建。为了实现您想要做的事情,您需要使用某种块压缩;例如
bgzip
(生成可以通过 plain 解压缩的文件gzip
)或bzip2
, 并在接收端做一些工作来确定块边界的位置。Peter Cock 写了一些关于这个主题的有趣帖子:BGZF - 被封锁、更大、更好的 GZIP!,随机访问BZIP2?只是FWIW,gzip可以随机访问,如果以前的索引文件已经创建......
我开发了一个命令行工具,如果提供了索引,它可以快速(几乎)随机访问 gzip(如果没有提供,则会自动创建):
https://github.com/circulosmeos/gztool
gztool
可用于访问原始 gzip 文件的块,如果这些块是在索引指向的特定字节点处检索到的(肯定是-1 字节,因为 gzip 是位流,而不是字节),或者更好,在他们之后。例如,如果索引点从gzip 文件的压缩字节1508611开始(
gztool -ll index.gzi
提供此数据),并且我们希望在此之后有 1M 压缩字节:chunk.gz
在磁盘上只会占用块大小!现在还必须检索完整的索引(以前只创建一次:例如,
gztool -i *.gz
为所有已压缩的文件创建索引,或同时压缩和创建索引)。gztool -c *
请注意,索引约为 gzip 大小的 0.3%(如果gztool
压缩数据本身,则要小得多)。现在可以使用gztool完成提取。必须知道compressed-1508610 的相应未压缩字节(或传递该字节的字节),但索引可以用
gztool -ll
. 请参阅此处的示例。假设它是字节 9009009。或者我们想要的未压缩字节只是传递了包含在 chunk.gz 中的相应第一个索引点。让我们再次假设在这种情况下这个字节也是 9009009。gztool
chunk.gz
文件结束时将停止提取数据。也许很棘手,但可以在不改变压缩方法或压缩文件的情况下运行。但是需要为它们创建索引。
注意:另一种不使用参数进行提取的方法是用稀疏零
-n
填充 gzip 文件:对于示例来说,这是在第一个检索文件之前使用命令完成的,因此:dd
curl
chunk.gz
这样,文件的前 1508609 个字节为零,但它们不占用磁盘空间。没有
seek
indd
命令,零都写入磁盘,这对 也有效gzip
,但这样我们就不会占用磁盘上不必要的空间。那么,gztool 命令就不需要这个-n
参数了。不需要归零的数据,因为索引存在,gztool
将使用它跳转到未压缩的 9009009 字节位置之前的索引点,因此所有先前的数据都将被忽略: