2009-10-22 93 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。

對於這些情況,只需在do {}循環中deflateStream.Read(s)一次,然後返回一個等於buffersize的未壓縮流,如果將緩衝區大小增加一個字節,則一切正常(除了丟失的字節)。

輸出爲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 

還要注意緩衝區大小的第三讀65536 ex:bytesRead:[58472]顯然,​​這也應該是65536,因爲緩衝區中仍有數據?

任何想法將大大讚賞。

TIA

  • 雅科
+0

你怎麼能說如果你不能解壓縮數據壓縮就好了? – 2009-10-22 14:35:56

+0

Hi Lasse, 我寫了另一個實現,其中相同數據集的壓縮大小等於流後壓縮的大小。 - 希望有道理 – twiga 2009-10-22 14:43:53

回答

4

您應該始終在壓縮流上調用Close()。請注意Flush()是不夠。我懷疑因爲這個,泄氣流缺少數據。

+0

首先,關閉沒有工作,因爲它關閉了基礎流以及。但在使用true選項創建deflatestream後調用.Close()以離開Open,我可以關閉它,並將基礎流傳回給調用者! tyvm! – twiga 2009-10-22 15:19:59

+0

DeflateStream是一個流,這意味着它是IDisposable。你需要一個使用條款。儘管Close()可能已經足夠,但您通過不調用Dispose()或將它放在using子句中來違反了使用模型。 – Cheeso 2009-10-23 05:54:07

3

我的精神力量告訴我,你在做實際上有一個工作減壓的實施,但已經忘記了之前刷新壓縮流。

+0

a DeflateStream.Close()糾正它tyvm – twiga 2009-10-22 15:21:03

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