2016-01-13 56 views
1

如果壓縮一些json文本,並使用FileStream將其寫入文件,我會得到預期的結果。但是,我不想寫入磁盤。我只是想要壓縮數據的內存。GZipStream在寫入FileStream時工作,但不是MemoryStream

壓縮到FileStream

string json = Resource1.json; 

using (MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes(json))) 
using (FileStream output = File.Create(@"C:\Users\roarker\Desktop\output.json.gz")) 
{ 
    using (GZipStream compression = new GZipStream(output, CompressionMode.Compress)) 
    { 
     input.CopyTo(compression); 
    } 
} 

上述工作。下面,輸出內存流的長度爲10,並生成一個空的.gz文件。

string json = Resource1.json; 

using (MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes(json))) 
using (MemoryStream output = new MemoryStream()) 
{ 
    using (GZipStream compression = new GZipStream(output, CompressionMode.Compress)) 
    { 
     input.CopyTo(compression); 

     byte[] bytes = output.ToArray(); 
    } 
} 

編輯: 移動output.ToArray()using條款之外似乎工作。但是,這會關閉大多數用法的輸出流。 IE:

 using (MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes(json))) 
     using (MemoryStream output = new MemoryStream()) 
     { 
      using (GZipStream compression = new GZipStream(output, CompressionMode.Compress)) 
      { 
       input.CopyTo(compression); 
      } 
      WriteToFile(output); 
     } 

其中:

public static void WriteToFile(Stream stream) 
    { 
     using (FileStream output = File.Create(@"C:\Users\roarker\Desktop\output.json.gz")) 
     { 
      stream.CopyTo(output); 
     } 
    } 

因爲流已經關閉,這將在stream.CopyTo失敗。我知道我可以從output.ToArray()的字節中創建一個新的Stream,但爲什麼這是必要的?爲什麼ToArray()在流關閉時工作?

最後編輯:

只需要使用GZipStream的構造器與leaveOpen參數。

+0

最後要說清楚,'bytes.Length == 10'。 – Dave

+1

如果您在內部使用塊的外部移動'byte [] bytes = output.ToArray();',你會得到相同的行爲嗎? – GalacticCowboy

+3

溪流像廁所。你沒有完成他們,直到他們被沖洗。除非你是某種令人厭惡的動物。我的意思是,真的。 – Will

回答

8

在您關閉GZipStream之前,您打電話給ToArray() ......這意味着它沒有機會刷新其緩衝區的最後一位。這是壓縮加密流的常見問題,關閉流需要編寫一些最終的數據。 (即使調用Flush()明確不會幫助,例如。)

只需推動ToArray電話:

using (MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes(json))) 
using (MemoryStream output = new MemoryStream()) 
{ 
    using (GZipStream compression = new GZipStream(output, CompressionMode.Compress)) 
    { 
     input.CopyTo(compression); 
    } 
    byte[] bytes = output.ToArray(); 
    // Use bytes 
} 

(請注意,當你調用ToArray流將被佈置,不過沒關係。)

+0

我很困惑,因爲輸出流被認爲是關閉的內部使用後。我可以使用ToArray()並獲取所有字節,但是我無法將'output'傳遞給其他函數,以像內存流一樣處理。這有意義嗎? – Dave

+0

@Dave:是的 - 基本上你正在使用'MemoryStream'的額外功能(它有內存中的數據),但是你不能將它用作普通流。能夠做到這一點非常方便 - 正是在這種情況下。 –

+0

我編輯了這個問題,但我想你說的是,如果我想訪問內存中的數據,我需要將這些字節複製到一個新的流? – Dave

相關問題