我正在尝试从git pack文件读出git对象,遵循布局here的包文件的格式。一旦我点击了压缩数据,我就遇到了问题。我正在尝试使用System.IO.Compression.DeflateStream来解压缩zlib压缩对象。我基本上通过跳过前2个字节来忽略zlib头。无论如何,第一个对象的这2个字节是789C。现在麻烦开始了。
1)我只知道解压缩对象的大小。 DeflateStream上的Read方法文档声明它“将大量解压缩的字节读入指定的字节数组中。”这就是我想要的,但是我确实看到人们将这个数量设置为压缩数据的大小,我们其中一个人做错了。
2)我想回来的数据是正确的,我认为(人类可读的数据看起来正确),然而它正在推进基础流我一直到最后!例如,我向它询问187个解压缩字节,并将剩余的212个字节一直读到流的末尾。因为在整个流中是228个字节,并且在deflate结尾处读取187个字节的流的位置现在是228.我不能向后搜索,因为我不知道压缩数据的结尾在哪里,并且也不是我使用的所有流都是可以寻找的。这是消耗整个流的预期行为吗?
答案 0 :(得分:0)
根据您引用的页面(我自己并不熟悉这种文件格式),每个数据块都由文件索引中的偏移字段索引。由于您知道每个数据块之前的类型和数据长度字段的长度,并且您知道下一个块的偏移量,因此您还知道每个数据块的长度(即压缩的长度字节)。
也就是说,每个数据块的长度只是下一个块的偏移量减去当前块的偏移量,然后减去类型和数据长度字段的长度(但是根据文档的数据...... ,它是可变的,但你可以在阅读时计算出这个长度。)
所以:
1)我只知道解压缩对象的大小。 DeflateStream上的Read方法文档声明它“将一些解压缩的字节读入指定的字节数组中”。这就是我想要的,但是我确实看到人们将这个数量设置为压缩数据的大小,我们其中一个人做错了。
文档是正确的。 DeflateStream
是Stream
的子类,必须遵循该类的规则。由于Read()
Stream
方法输出所请求的字节数,因此这些方法必须是未压缩的字节。
请注意,根据上述内容,您 知道压缩对象的大小。它不存储在文件中,但您可以从存储在文件中 的内容中获取该信息。
2)我想回来的数据是正确的,我认为(人类可读的数据看起来正确),然而它正在推进基础流我一直到最后!例如,我向它询问187个解压缩字节,并将剩余的212个字节一直读到流的末尾。因为在整个流中是228个字节,并且在deflate结尾处读取187个字节的流的位置现在是228.我不能向后搜索,因为我不知道压缩数据的结尾在哪里,并且也不是我使用的所有流都是可以寻找的。这是消耗整个流的预期行为吗?
是的,我希望这会发生。或者至少,我希望会发生一些缓冲,所以即使它没有一直读到流的末尾,我希望它能够读取压缩数据末尾的至少一些字节数
在我看来,你至少有几个选择:
MemoryStream
对象,然后解压缩该流中的数据而不是原始数据。