2009-10-22 3 views
2

Интересно, если кто-то может пролить некоторый свет на вопрос, который сводит меня с ума:Непонятные .Net C# DeflateStream проблема

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

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

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 {}, а затем возвращает несжатый поток, равный буферизации, если вы увеличиваете буферизацию по одному байту, все хорошо (за исключением отсутствующего байта).

Выхода для BufferSize 65536: (Original несжатых данных 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] 

BufferSize из 189544 (Some магического числа, где код цистерна)

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

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

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

ТИА

  • Жако
+0

Как вы можете сказать, что сжатие прекрасное, если вы не можете распаковать данные? –

+0

Hi Lasse, Я написал еще одну реализацию, где сжатый размер одного и того же набора данных равен размеру сжатия постпотока. - Надеюсь, что имеет смысл – twiga

ответ

4

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

+0

Сначала Close не работал, потому что он также закрыл базовый поток. Но вызов .Close() после того, как deflatestream был создан с помощью истинной опции leaveOpen, я мог закрыть его, и базовый поток был передан обратно вызывающему абоненту! tyvm! – twiga

+0

DeflateStream - это Stream, что означает, что он IDisposable. Вам нужно использовать предложение. Хотя Close() может быть достаточным, вы нарушили модель использования, не вызвав Dispose() или не включив его в предложение use. – Cheeso

3

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

+0

a DeflateStream.Close() выпрямил его tyvm – twiga

0

Ну, я не мог определить вашу проблему, но следуйте некоторому коду, который я написал когда-то за 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); 
Смежные вопросы