假设有一个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
只是FWIW,如果已经创建了以前的索引文件,则可以随机访问gzip ......
我开发了一个命令行工具,如果提供了索引,它可以快速且(几乎)随机地访问 gzip(如果未提供,则会自动创建):
https://github.com/circulosmeos/gztool
gztool
可以用来访问原始 gzip 文件的块,如果这些块是在索引指向的特定字节点检索的(当然是 -1 字节,因为 gzip 是位流,而不是字节),或者更好,在他们之后。
例如,如果索引点gztool -ll index.gzi
从 gzip 文件的压缩字节1508611开始(提供此数据) ,并且我们希望之后有 1M 压缩字节:
$ curl -r 1508610-2508611 https://example.com/db/backups/db.sql.gz > chunk.gz
Run Code Online (Sandbox Code Playgroud)
chunk.gz
只会占用磁盘上的块大小!现在,还必须检索完整的索引(以前仅创建一次:例如gztool -i *.gz
为所有已 gzip 压缩的文件创建索引,或者gztool -c *
压缩并创建索引)。gztool
请注意,索引约为 gzip 大小的 0.3%(如果压缩数据本身,则索引会小得多)。
$ curl https://example.com/db/backups/db.sql.gzi -o chunk.gzi
Run Code Online (Sandbox Code Playgroud)
现在可以使用gztool来完成提取。压缩 1508610 的相应未压缩字节(或传递该字节的字节)必须已知,但索引可以使用gztool -ll
. 请参阅此处的示例。假设它是字节 9009009。或者我们想要的未压缩字节只是传递给 chunk.gz 中包含的相应第一个索引点。让我们再次假设在这种情况下该字节也将是 9009009。
$ gztool -n 1508610 -b 9009009 chunk.gz > extracted_chunk.sql
Run Code Online (Sandbox Code Playgroud)
gztool
当文件结束时将停止提取数据chunk.gz
。
也许很棘手,但可以在不改变压缩方法或已经压缩的文件的情况下运行。但需要为它们创建索引。
注意:不使用参数进行提取的另一种方法是用稀疏-n
零填充 gzip 文件:对于示例来说,这是在第一个检索文件之前使用命令完成的,因此:dd
curl
chunk.gz
$ dd if=/dev/zero of=chunk.gz seek=1508609 bs=1 count=0
$ curl -r 1508610-2508611 https://example.com/db/backups/db.sql.gz >> chunk.gz
$ curl https://example.com/db/backups/db.sql.gzi -o chunk.gzi
Run Code Online (Sandbox Code Playgroud)
这样,文件的前 1508609 字节为零,但它们不占用磁盘空间。如果没有seek
indd
命令,零将全部写入磁盘,这对于 也有效gzip
,但这样我们就不会占用磁盘上不必要的空间。那么,gztool命令就不需要该-n
参数了。不需要清零的数据,因为当索引存在时,gztool
将使用它跳转到未压缩的 9009009 字节位置之前的索引点,因此所有先前的数据都将被忽略:
$ gztool -b 9009009 chunk.gz > extracted_chunk.sql
Run Code Online (Sandbox Code Playgroud)
gzip
\xe2\x80\x99 不会生成块压缩文件(有关详细信息,请参阅RFC),因此它\xe2\x80\x99 本身不适合随机访问。您可以开始从流中读取数据并随时停止,这就是您的curl -r 0-2024
示例有效的原因,但是您可以 \xe2\x80\x99t 在中间拾取流,除非您有一个补充文件来提供丢失的数据(例如作为由 ) 创建的索引文件gztool
。
为了实现您\xe2\x80\x99想要做的事情,您需要使用某种类型的块压缩;例如 bgzip
(生成可以通过 plain 解压缩的文件gzip
)或bzip2
,并在接收端做一些工作以确定块边界所在的位置。Peter Cock 就该主题写了几篇有趣的文章:BGZF - Blocked, Bigger & Better GZIP!,随机访问BZIP2?