2013-06-20 69 views
4

根據.Net 4.5中的MSDN,System.IO.Compression基於zlib。
我現在正在嘗試將當前基於互操作的讀取從zlib壓縮流從非.NET服務器轉換爲基於BCL的實現。
我的實現看起來是這樣的:.Net zlib使用.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;
有沒有人試過相同的o r在代碼中看到錯誤的原因,或者在我的結尾有錯誤的理解? 我也嘗試過截斷前兩個字節沒有任何運氣。
前幾個字節是20,202,177,13。

回答

6

您試圖壓縮的數據的前幾個字節是什麼?

您可能會嘗試解碼zlib,gzip或raw deflate數據。

順便說一句,我強烈建議您使用DotNetZip's接口zlib而不是NET 4.5(或NET任何版本)。 NET 4.5在微軟聲明他們won't fix(!)的接口中存在錯誤。

+0

有我的計劃,我現在已經解決的另一個錯誤,現在運轉。我的理解是,從版本4.5開始就使用二進制zlib版本 - 這是我爲什麼執行切換的背景。出於性能考慮,我之前使用的是本地版本。 – weismat

+0

需要糾正自己 - 它僅適用於幾次讀取 - 很可能與內存流有關。將進一步調查。 – weismat

+0

雖然他們終於切換到4.5中使用zlib,這固定了一堆真正的腦死亡問題,但zlib的接口卻搞砸了,他們不會修復它。所以我建議回到本地或使用DotNetZip。 –

16

上面的答案是正確的,但對「爲什麼」並不完全清楚。原始ZLib流的前兩個字節提供了有關使用的壓縮類型的詳細信息。 System.Io.Compression中的Microsoft DeflateStream類不理解這些。修正如下:

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文件的Byte []。將它加載到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(); 
}