Загадочная проблема .Net C # DeflateStream - PullRequest
2 голосов
/ 22 октября 2009

Интересно, кто-нибудь может пролить свет на проблему, которая сводит меня с ума:

Я пишу тестовый декомпрессионный класс. Чтобы проверить это, я сериализирую набор данных в поток памяти, сжимаю его, распаковываю и сравниваю результаты.

Сжатие в порядке, но несжатие - это то место, где оно попадает в грязь. Это функция распаковки:

    public static Stream GetUncompressedStreamCopy(Stream inStream)
    {
      Stream outStream = new MemoryStream();

      inStream.Position = 0;

      DeflateStream uncompressStream = new DeflateStream(inStream, 
        CompressionMode.Decompress, true);

      byte[] buffer = new byte[65536];

      int totalread = 0;
      int bytesread = 0;


      do {
        bytesread = uncompressStream.Read(buffer, 0, buffer.Length);
        totalread += bytesread;
        outStream.Write(buffer, 0, bytesread);
        Console.WriteLine("bytesRead: [{0}]\t outStream.Length [{1}]",
        bytesread, outStream.Length);
      } while (bytesread > 0);


      Console.WriteLine("total bytes read [{0}]", totalread);
      outStream.Flush();
      return outStream;
}

С буфером размером 65536 распакованный поток всегда возвращает на один байт меньше, чем был распакован.

Теперь это подводит меня ко второму вопросу, с которым я борюсь. При некоторых размерах буфера uncompressStream.Read возвращает 0, даже если для извлечения остаются сжатые данные.

В этих случаях deflateStream.Read (s) только один раз в цикле do {}, а затем возвращает несжатый поток, равный размеру буфера, если вы увеличиваете размер буфера на один байт, все хорошо (за исключением отсутствующего байта) .

Вывод для размера буфера 65536: (Исходные несжатые данные - 207833)

bytesRead: [65536]       outStream.Length [65536]
bytesRead: [65536]       outStream.Length [131072]
bytesRead: [58472]       outStream.Length [189544]
bytesRead: [18288]       outStream.Length [207832]
bytesRead: [0]           outStream.Length [207832]
total bytes read [207832]

размер буфера 189544 (какое-то магическое число, где код танков)

bytesRead: [189544]      outStream.Length [189544]
bytesRead: [0]           outStream.Length [189544]
total bytes read [189544]
Unompressed stream size 189544

Также обратите внимание на 3-е чтение размера буфера 65536, например: bytesRead: [58472] Очевидно, что это также должно быть 65536, так как в буфере остались данные?

Любые идеи будут очень оценены.

ТИА

  • Жако

Ответы [ 3 ]

5 голосов
/ 22 октября 2009

Вы всегда должны вызывать Close () для потоков сжатия. Обратите внимание, что Flush () недостаточно . Я подозреваю, что из-за этого в потоке дефлята отсутствуют данные.

3 голосов
/ 22 октября 2009

Мои психические способности говорят мне, что у вас действительно есть работающая реализация декомпрессии, но вы забыли очистить поток сжатия раньше.

0 голосов
/ 22 октября 2009

Ну, я не могу определить вашу проблему, но следуйте некоторому коду, который я написал некоторое время назад для ICSharpCode.SharpZipLib ;

byte[] compressedData;
using(MemoryStream ms = new MemoryStream())
{
    Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, true);
    Stream s = new DeflaterOutputStream(ms, deflater);
    s.Write(sendData, 0, sendData.Length);
    s.Close();
    compressedData = (byte[])ms.ToArray();
}

// ...

MemoryStream inflated = new MemoryStream();
using (Stream inflater = new InflaterInputStream(
    inputStream, new Inflater(true)))
{
    int count = 0;
    byte[] deflated = new byte[4096];
    while ((count = inflater.Read(deflated, 0, deflated.Length)) != 0)
    {
        inflated.Write(deflated, 0, count);
    }
    inflated.Seek(0, SeekOrigin.Begin);
}
byte[] content = new byte[inflated.Length];
inflated.Read(content, 0, content.Length);
...