2013-06-20 3 views
4

Согласно MSDN в .Net 4.5 System.IO.Compression основан на zlib.
Я пытаюсь теперь изменить текущее чтение на основе interop из потока сгенерированного zlib с не .NET-сервера в реализацию на основе BCL.
Моя реализация выглядит следующим образом:.Net zlib inflate with .Net 4.5

var enc = new UTF8Encoding();    
     var readBytes = BufferSizeRaw; 
     var outputBuffer = new byte[BufferSizeRaw];    
     var networkBuffer = _networkQueue.Take(); 
     var ms = new MemoryStream(networkBuffer.InputBuffer, 0, networkBuffer.UsedLength); 
     using (Stream stream = new DeflateStream(ms, CompressionMode.Decompress)) 
      while (readBytes==BufferSizeRaw) 
      { 
       readBytes = stream.Read(outputBuffer, 0, outputBuffer.Length);     
       stringBuffer+= enc.GetString(outputBuffer, 0, readBytes);     
      } 

Я получаю следующее исключение на первом вызове декомпрессию/чтения на DeflateStream:

Длина блока не совпадает с его дополнением

Взаимодействующий вызов использует var result=inflate(ref zStyream, ZLibFlush.NoFlush;
Кто-нибудь пробовал то же самое r видит причину ошибки в коде или есть неправильное понимание на моем конце? Я также пробовал его с усечением первых двух байтов без везения.
Первые несколько байтов - 20, 202, 177,13.

ответ

6

Каковы первые несколько байтов данных, которые вы пытаетесь сжать?

Возможно, у вас есть данные zlib, gzip или raw deflate, которые вы пытаетесь декодировать.

Кстати, я настоятельно рекомендую вам использовать интерфейс DotNetZip's для zlib вместо NET 4.5 (или NET любой версии). NET 4.5 имеет ошибки в этом интерфейсе, которые Microsoft заявила, что они won't fix (!).

+0

Был еще ошибка в моей программе, которую я уже устранили, и он работает в настоящее , Я понимаю, что с версии 4.5 используется двоичная zlib-версия, что является фоном, почему я сделал переключатель. Раньше я использовал родную версию по соображениям производительности. – weismat

+0

Нужно исправить себя - он работает только для нескольких чтений - скорее всего, это связано с потоком памяти. Изучит его дальше. – weismat

+0

Пока они наконец-то переключились на использование zlib в 4.5, который зафиксировал кучу действительно проблем с мозгом, интерфейс к zlib перепутался, и они не будут исправлять его. Поэтому я рекомендую вернуться к родному или использовать DotNetZip. –

16

Ответ выше правильный, но не совсем ясно, почему «почему». Первые два байта исходного потока ZLib содержат сведения о типе используемого сжатия. Класс DeflateStream от Microsoft в System.Io.Compression не понимает их. Фиксация заключается в следующем:

using (MemoryStream ms = new MemoryStream(data)) 
{ 
    MemoryStream msInner = new MemoryStream(); 

    // Read past the first two bytes of the zlib header 
    ms.Seek(2, SeekOrigin.Begin); 

    using (DeflateStream z = new DeflateStream(ms, CompressionMode.Decompress)) 
    { 
     z.CopyTo(msInner); 

В этом примере данные представляют собой байт [] с необработанным файлом Zlib. После загрузки в MemoryStream мы просто «ищем» первые два байта.

Сообщение объясняет, как выглядит заголовок Zlib, если вы смотрите на необработанные байты.

What does a zlib header look like?

4

Вот пересмотренный вариант ответа ProVega, который раздувает массив байтов в строку:

using (var stream = new MemoryStream(bytes,2, bytes.Length - 2)) 
using (var inflater = new DeflateStream(stream, CompressionMode.Decompress)) 
using (var streamReader = new StreamReader(inflater)) 
{ 
    return streamReader.ReadToEnd(); 
}