解码git对象/“块长度与其补码不匹配”错误

时间:2011-12-02 10:18:33

标签: c# git dvcs low-level

我遇到了非常简单但烦人的问题,并且无法在互联网上找到答案。希望你能指出我,我做错了什么。

我正在尝试从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

任何想法都将不胜感激!

2 个答案:

答案 0 :(得分:7)

DeflateStreamzlib是两个不同的事情,如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运行之前切断数据的前两个字节和最后四个字节。它是一个肮脏的解决方案,但可以帮助您避免引入外部依赖。