2012-05-15 298 views
16

我試圖使用Compression.DeflateStream壓縮和解壓縮流。由於下面的代碼將我的Stream壓縮爲110字節長的數組,因此壓縮似乎正常工作。但是,讀取解壓縮的流會產生一個空字符串。使用Compression.DeflateStream壓縮和解壓縮流

class Program 
{ 
    static void Main(string[] args) 
    { 
     // Compress a random string value 
     string value = Path.GetRandomFileName(); 
     byte[] compressedBytes; 

     using (var writer = new StreamWriter(new MemoryStream())) 
     { 
      writer.Write(value); 
      writer.Flush(); 
      writer.BaseStream.Position = 0; 

      compressedBytes = Compress(writer.BaseStream); 
     } 

     // Decompress compressed bytes 
     Stream decompressedStream = Decompress(compressedBytes); 
     // here already applies: decompressedStream.Length == 0 

     using (var reader = new StreamReader(decompressedStream)) 
     { 
      string decompressedValue = reader.ReadToEnd(); 

      if (value == decompressedValue) 
       Console.WriteLine("Success"); 
      else 
       Console.WriteLine("Failed"); 
     } 
    } 

    private static byte[] Compress(Stream input) 
    { 
     using (var compressStream = new MemoryStream()) 
     using (var compressor = new DeflateStream(compressStream, CompressionMode.Compress)) 
     { 
      input.CopyTo(compressor); 
      return compressStream.ToArray(); 
     } 
    } 

    private static Stream Decompress(byte[] input) 
    { 
     var output = new MemoryStream(); 

     using (var compressStream = new MemoryStream(input)) 
     using (var decompressor = new DeflateStream(compressStream, CompressionMode.Decompress)) 
      decompressor.CopyTo(output); 

     output.Position = 0; 
     return output; 
    } 
} 

任何人都可以幫助我解決這個問題嗎? 非常感謝。

回答

25

解決您的Compress功能:

private static byte[] Compress(Stream input) 
{ 
    using(var compressStream = new MemoryStream()) 
    using(var compressor = new DeflateStream(compressStream, CompressionMode.Compress)) 
    { 
     input.CopyTo(compressor); 
     compressor.Close(); 
     return compressStream.ToArray(); 
    } 
} 

壓縮數據流並沒有返回結果的字節數組之前沖刷。

+0

This works。非常感謝 – greijner

+3

如果您調用'Flush'而不是'Close',則不能使用。我認爲'Close'在內部調用'Flush'就是爲什麼這個工作,但沒有。 –

+4

@Luke:from [DeflateStream.Flush()']的文檔(https://msdn.microsoft.com/en-us/library/system.io.compression.deflatestream.flush(v = vs.110) .aspx):_「這個方法的當前實現不會刷新內部緩衝區,當對象被丟棄時內部緩衝區被刷新。」至於爲什麼這是設計,'Stream.Flush()'是爲了沖洗內部緩衝,但deflate流只有知道您在_end_時才能最終確定,這隻有在流_closed_時纔有可能。 –

9

嘗試關閉流:

class Program 
{ 
    static void Main(string[] args) 
    { 
     // Compress a random string value 
     string value = DateTime.Now.ToLongTimeString(); 
     byte[] compressedBytes; 

     using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(value))) 
     { 
      compressedBytes = Compress(stream); 
     } 


     // Decompress compressed bytes 
     using (var decompressedStream = Decompress(compressedBytes)) 
     using (var reader = new StreamReader(decompressedStream)) 
     { 
      string decompressedValue = reader.ReadToEnd(); 

      if (value == decompressedValue) 
       Console.WriteLine("Success"); 
      else 
       Console.WriteLine("Failed"); 
     } 
    } 

    public static byte[] Compress(Stream input) 
    { 
     using (var compressedStream = new MemoryStream()) 
     using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) 
     { 
      input.CopyTo(zipStream); 
      zipStream.Close(); 
      return compressedStream.ToArray(); 
     } 
    } 

    public static Stream Decompress(byte[] data) 
    { 
     var output = new MemoryStream(); 
     using(var compressedStream = new MemoryStream(data)) 
     using(var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress)) 
     { 
      zipStream.CopyTo(output); 
      zipStream.Close(); 
      output.Position = 0; 
      return output; 
     } 
    } 
} 
+1

我使用相同的壓縮解壓縮功能。解壓縮工作正常,但返回的Stream對象給我。無法訪問關閉的流。消息,而我正在努力工作。相同的代碼在壓縮解壓縮函數之前正在工作。任何想法? – afr0

4

所有這些問題的答案都在遠離理想形式,因爲你們忘了,「使用」部署和閉合流的手段,額外的關閉()是不必要的。我認爲理想的代碼將如下所示:

public static class CompressionHelper 
{ 
    public static byte[] Compress(byte[] data) 
    { 
     byte[] compressArray = null; 
     try 
     { 
      using (MemoryStream memoryStream = new MemoryStream()) 
      { 
       using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress)) 
       { 
        deflateStream.Write(data, 0, data.Length); 
       } 
       compressArray = memoryStream.ToArray(); 
      } 
     } 
     catch (Exception exception) 
     { 
      // do something ! 
     } 
     return compressArray; 
    } 

    public static byte[] Decompress(byte[] data) 
    { 
     byte[] decompressedArray = null; 
     try 
     { 
      using (MemoryStream decompressedStream = new MemoryStream()) 
      { 
       using (MemoryStream compressStream = new MemoryStream(data)) 
       { 
        using (DeflateStream deflateStream = new DeflateStream(compressStream, CompressionMode.Decompress)) 
        { 
         deflateStream.CopyTo(decompressedStream); 
        } 
       } 
       decompressedArray = decompressedStream.ToArray(); 
      } 
     } 
     catch (Exception exception) 
     { 
      // do something ! 
     } 

     return decompressedArray; 
    } 
}