2011-12-02 20 views
5

Utknąłem z bardzo prostym, ale denerwującym problemem i nie mogę znaleźć odpowiedzi w Internecie. Mam nadzieję, że będziesz w stanie wskazać mi, co zrobiłem źle.Dekodowanie obiektów git/"Długość bloku nie jest zgodna z jego dopełnieniem" błąd

Próbuję odszyfrować obiekt z repozytorium Git. Zgodnie z ProGit, nazwa pliku i jego zawartość zostały odrzucone podczas zatwierdzania.

Używam C# do odczytu obiektu wskazanego przez SHA1 do strumienia, nadmuchać go i przekształcić w tablicy bajtowej. Oto kod:

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; 
} 

Kiedy gs.CopyTo(ms); osiągnięciu błędu wykonawczego następuje: długość bloku nie zgadza się z jego dopełnieniem.

Dlaczego tak jest?

Odnośnie zawartości pliku próbuję przeczytać ... Jest to plik binarny, który został utworzony przez plik wykonywalny git. Oryginalna nazwa pliku to testfile.txt, jego treść to Sample text. SHA1 to 51d0be227ecdc0039698122a1513421ce35c1dbe.

Każdy pomysł zostanie bardzo doceniony!

Odpowiedz

7

DeflateStream i zlib to dwie różne rzeczy, jak wyjaśniono w this answer:

Nie ma ZlibStream w bibliotece klasy bazowej .NET - nic, co produkuje lub pobiera zlib

Więc co Cię potrzeba jest konsumentem ZLIB. Biblioteka DotNetZip zapewnia jeden:

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); 
} 
+0

Dziękuję, to było naprawdę pomocne! – shytikov

2

ZLib jest Deflate z dodatkowym dwóch bajtów nagłówka, opcjonalny „słownika” i cztery bajt sumy kontrolnej na końcu. W zależności od aplikacji - np. Jeśli wiesz, że nie będzie słownika - możesz uciąć sobie odrywanie pierwszych dwóch bajtów i ostatnich czterech bajtów od danych przed uruchomieniem go przez DeflateStream. To brudne rozwiązanie, ale może uratować cię od konieczności wprowadzenia zewnętrznej zależności.