$ cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip
gzip: stdin: not in gzip format
$ cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip
gzip: stdin: not in gzip format
Git对象使用zlib
进行压缩,而不是gzip
,因此可以使用zlib
解压缩,或者使用git命令,例如git cat-file -p <SHA1>
打印内容。
git cat-file -p <SHA1>
的输出并不是.git/objects/<SHA1>
的zlib解压缩的完整内容。如果你想要实现一个Git提交哈希计算器,这种差异是关键的... - ntc2// save this as deflate.go
package main
import (
"compress/zlib"
"io"
"os"
"flag"
)
var infile = flag.String("f", "", "infile")
func main() {
flag.Parse()
file, _ := os.Open(*infile)
r, err := zlib.NewReader(file)
if err != nil {
panic(err)
}
io.Copy(os.Stdout, r)
r.Close()
}
$ go build deflate.go
$ ./deflate -f .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7
pigz可以完成这项任务:
apt-get install pigz
unpigz -c .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7
从 Bash 类似的 shell 中:
perl -mIO::Uncompress::RawInflate=rawinflate -erawinflate'"-","-"'
或者,如果您手动执行/分叉(没有Shell引号,但是分隔行):
perl
-mIO::Uncompress::RawInflate=rawinflate
-erawinflate"-","-"
重要提示:如果流不以有效的DEFLATE流(例如未压缩的数据)开头,则此命令将愉快地传输所有数据。只有当流以有效的DEFLATE流(带有有效的字典,我想?我不太确定...)开始时,然后此命令将以某种方式出错。在某些情况下,这可能是可取的。
希望这能帮助任何时空旅行者。
参考资料:
这是我使用 Powershell 的方法。
$fs = New-Object IO.FileStream((Resolve-Path $Path), [IO.FileMode]::Open, [IO.FileAccess]::Read)
$fs.Position = 2
$cs = New-Object IO.Compression.DeflateStream($fs, [IO.Compression.CompressionMode]::Decompress)
$sr = New-Object IO.StreamReader($cs)
$sr.ReadToEnd()
然后,您可以创建一个别名,例如:
function func_deflate{
param(
[Parameter(Mandatory=$true, ValueFromPipeline = $true)]
[ValidateScript({Test-Path $_ -PathType leaf})]
[string]$Path
)
$ErrorActionPreference = 'Stop'
$fs = New-Object IO.FileStream((Resolve-Path $Path), [IO.FileMode]::Open, [IO.FileAccess]::Read)
$fs.Position = 2
$cs = New-Object IO.Compression.DeflateStream($fs, [IO.Compression.CompressionMode]::Decompress)
$sr = New-Object IO.StreamReader($cs)
return $sr.ReadToEnd()
}
Set-Alias -Name deflate -Value func_deflate
为了丰富收藏,这里提供一些用于压缩/解压缩/原始压缩/原始解压缩的 Perl 单行命令。
压缩
perl -MIO::Compress::Deflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Compress::Deflate::deflate(\$in, \$out); print $out;'
解压
perl -MIO::Uncompress::Inflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Uncompress::Inflate::inflate(\$in, \$out); print $out;'
原始压缩
perl -MIO::Compress::RawDeflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Compress::RawDeflate::rawdeflate(\$in, \$out); print $out;'
原始解压缩
perl -MIO::Uncompress::RawInflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Uncompress::RawInflate::rawinflate(\$in, \$out); print $out;'
我发现这个问题是在寻找一个解决方案,因为我刚刚安装了新版本的 hadoop dfs
客户端中的 -text
实用程序存在一个 bug。 -text
实用程序类似于 cat
,但是如果要读取的文件被压缩,它会透明地解压缩并输出纯文本(因此得名)。
已经发布的答案肯定有帮助,但其中一些在处理大量 Hadoop 数据时会有一个问题-在解压缩之前将所有内容读入内存中。
因此,这里是我对上面 Perl
和 Python
答案的变化,没有那种限制:
Python:
hadoop fs -cat /path/to/example.deflate |
python -c 'import zlib,sys;map(lambda b:sys.stdout.write(zlib.decompress(b)),iter(lambda:sys.stdin.read(4096),""))'
Perl:
hadoop fs -cat /path/to/example.deflate |
perl -MCompress::Zlib -e 'print uncompress($buf) while sysread(STDIN,$buf,4096)'
-cat
子命令,而不是-text
。这样做是为了避免在他们修复错误后我的解决方法失效。对于Python版本的可读性不佳,深感抱歉。请查看http://en.wikipedia.org/wiki/DEFLATE#Encoder_implementations。
它列出了许多软件实现,包括gzip,所以应该可以使用。您是否尝试过直接在文件上运行gzip?它不能自动识别格式吗?
您如何知道它是使用DEFLATE压缩的?使用什么工具压缩文件?
为什么不直接使用git的工具来访问数据呢?这应该能够读取任何git对象:
git show --pretty=raw <object SHA-1>
git cat-file -p c0fb67ab3fda7909000da003f4b2ce50a53f43e7
可以查看 Git 存储库中对象 ID 为 c0fb67ab3fda7909000da003f4b2ce50a53f43e7 的对象的内容。 - Jakub Narębski