2010-10-03 89 views
2

在我的應用程序中,我需要解壓縮由DataContractSerializer編寫的數據,以在另一個應用程序中壓縮Deflate Stream,編輯解壓縮的數據並再次壓縮它。壓縮和解壓縮源數據給出的結果不同於源數據

解壓縮工作正常,但不適用於我壓縮的數據。

問題是,當我這樣做: byte [] result = Compressor.Compress(Compressor.Decompress(sourceData));

結果字節數組的長度不同於sourceData數組。

例如:

string source = "test value"; 
    byte[] oryg = Encoding.Default.GetBytes(source); 

    byte[] comp = Compressor.Compress(oryg); 
    byte[] result1 = Compressor.Decompress(comp); 

    string result2 = Encoding.Default.GetString(res); 

這裏result1.Length爲0,結果2是 「」 當然

這裏是我的壓縮機類的代碼。

public static class Compressor 
{ 
    public static byte[] Decompress(byte[] data) 
    { 
     byte[] result; 

     using (MemoryStream baseStream = new MemoryStream(data)) 
     { 
      using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Decompress)) 
      { 
       result = ReadFully(stream, -1); 
      } 
     } 

     return result; 
    } 

    public static byte[] Compress(byte[] data) 
    { 
     byte[] result; 

     using (MemoryStream baseStream = new MemoryStream()) 
     { 
      using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Compress, true)) 
      { 
       stream.Write(data, 0, data.Length); 
       result = baseStream.ToArray(); 
      } 
     } 

     return result; 
    } 

    /// <summary> 
    /// Reads data from a stream until the end is reached. The 
    /// data is returned as a byte array. An IOException is 
    /// thrown if any of the underlying IO calls fail. 
    /// </summary> 
    /// <param name="stream">The stream to read data from</param> 
    /// <param name="initialLength">The initial buffer length</param> 
    private static byte[] ReadFully(Stream stream, int initialLength) 
    { 
     // If we've been passed an unhelpful initial length, just 
     // use 32K. 
     if (initialLength < 1) 
     { 
      initialLength = 65768/2; 
     } 

     byte[] buffer = new byte[initialLength]; 
     int read = 0; 

     int chunk; 
     while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0) 
     { 
      read += chunk; 

      // If we've reached the end of our buffer, check to see if there's 
      // any more information 
      if (read == buffer.Length) 
      { 
       int nextByte = stream.ReadByte(); 

       // End of stream? If so, we're done 
       if (nextByte == -1) 
       { 
        return buffer; 
       } 

       // Nope. Resize the buffer, put in the byte we've just 
       // read, and continue 
       byte[] newBuffer = new byte[buffer.Length * 2]; 
       Array.Copy(buffer, newBuffer, buffer.Length); 
       newBuffer[read] = (byte)nextByte; 
       buffer = newBuffer; 
       read++; 
      } 
     } 
     // Buffer is now too big. Shrink it. 
     byte[] ret = new byte[read]; 
     Array.Copy(buffer, ret, read); 
     return ret; 
    } 
} 

如果可以的話,請幫助我解決這個問題。 最好的問候, 亞當

回答

3

(編輯:利用沖洗,仍然可能無法清除所有字節,到現在爲止,確保放氣首先配置切換,按照菲爾的答案在這裏:zip and unzip string with Deflate

之前嘗試從後備存儲中讀取,必須確保壓縮時deflate流已經完全刷新,允許deflate完成壓縮並寫入最終字節。關閉放氣蒸汽,或處理它,將達到此目的。

public static byte[] Compress(byte[] data) 
{ 
    byte[] result; 

    using (MemoryStream baseStream = new MemoryStream()) 
    { 
     using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Compress, true)) 
     { 
      stream.Write(data, 0, data.Length); 
     } 
     result = baseStream.ToArray(); // only safe to read after deflate closed 
    } 

    return result; 
}  

此外,您的ReadFully例程看起來非常複雜,並可能有錯誤。 一個是:

while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0) 

當讀取第二組塊,read會比緩衝器的長度時,這意味着它永遠傳遞一個負值到stream.Read爲要讀取的字節數。我的猜測是,它永遠不會讀第二塊,返回零,並從while循環中退出。

我建議喬恩的版本的readFully爲此目的: Creating a byte array from a stream

+0

非常感謝意志!你爲我節省了很多時間! – Nomann 2010-10-03 07:28:35

+0

Kewl,很高興幫助。你介意把這個問題標記爲回答嗎?乾杯! – Will 2010-10-03 09:36:55