我遇到了非常简单但烦人的问题,并且无法在互联网上找到答案。希望你能指出我,我做错了什么。
我正在尝试从Git存储库中解码对象。根据{{3}},文件名及其内容在提交期间已被缩小。
我正在使用C#将SHA1指示的对象读入流中,将其充气并转换为字节数组。这是代码:
using System.IO.Compression;
static internal byte[] GetObjectBySha(string storagePath, string sha)
{
string filePath = Path.Combine(storagePath, "objects", sha.Substring(0, 2), sha.Substring(2, 38));
byte[] fileContent = null;
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (MemoryStream ms = new MemoryStream())
{
using (DeflateStream gs = new DeflateStream(fs, CompressionMode.Decompress))
{
gs.CopyTo(ms);
}
fileContent = ms.ToArray();
}
}
return fileContent;
}
当达到gs.CopyTo(ms);
时,会发生运行时错误:块长度与其补码不匹配。
为什么这样?
关于我正在尝试阅读的文件的内容......它是二进制的,它是由git可执行文件创建的。原始文件名为testfile.txt
,其内容为Sample text.
,SHA1为51d0be227ecdc0039698122a1513421ce35c1dbe
。
任何想法都将不胜感激!
答案 0 :(得分:7)
DeflateStream
和zlib
是两个不同的事情,如this answer中所述:
.NET基类库中没有ZlibStream - 没有 生产或消费ZLIB
所以你需要的是一个ZLIB消费者。 DotNetZip库提供了一个:
static internal byte[] GetObjectBySha(string storagePath, string sha)
{
string filePath = Path.Combine(storagePath, "objects", sha.Substring(0, 2), sha.Substring(2, 38));
byte[] compressed = File.ReadAllBytes(filePath);
return Ionic.Zlib.ZlibStream.UncompressBuffer(compressed);
}
答案 1 :(得分:2)
ZLib是Deflate,带有一个额外的两个字节的头,一个可选的"字典"最后是一个四字节校验和。根据您的应用程序 - 如果您知道不会成为字典 - 您可以在通过DeflateStream运行之前切断数据的前两个字节和最后四个字节。它是一个肮脏的解决方案,但可以帮助您避免引入外部依赖。