2011-09-28 17 views
7

我想將大的UInt16數組保存到文件中。 positionCnt大約是50000,stationCnt大約是2500.直接保存,沒有GZipStream,文件大小約爲250MB,可以通過外部zip程序壓縮到19MB。使用下面的代碼文件是507MB。我做錯了什麼?GZipStream效果

GZipStream cmp = new GZipStream(File.Open(cacheFileName, FileMode.Create), CompressionMode.Compress); 
BinaryWriter fs = new BinaryWriter(cmp); 
fs.Write((Int32)(positionCnt * stationCnt)); 
for (int p = 0; p < positionCnt; p++) 
{ 
    for (int s = 0; s < stationCnt; s++) 
    { 
     fs.Write(BoundData[p, s]); 
    } 
} 
fs.Close(); 
+0

是什麼樣子,如果你將其壓縮*使用gzip *外部? –

+0

外部gzip給出大約19.5 MB; bzip2小於8MB – danatel

回答

12

不確定你運行的是哪個版本的.NET。在較早的版本中,它使用與您寫入的緩衝區大小相同的窗口大小。所以在你的情況下,它會嘗試單獨壓縮每個整數。我在認爲他們改變了.NET 4.0,但還沒有證實。

在任何情況下,你要做的就是創建一個緩衝流的GZipStream未來是什麼:

//創建一個具有64 KB緩衝 的FileStream FS =新的FileStream(文件名,FileMode.Create文件流, FileAccess.Write,FileShare.None,65536); GZipStream cmp = new GZipStream(fs,CompressionMode.Compress); ...

GZipStream cmp = new GZipStream(File.Open(cacheFileName, FileMode.Create), CompressionMode.Compress); 
BufferedStream buffStrm = new BufferedStream(cmp, 65536); 
BinaryWriter fs = new BinaryWriter(buffStrm); 

這樣,GZipStream在64個字節塊獲取數據,並能做到壓縮的一個更好的工作。

大於64KB的緩衝區不會給你更好的壓縮。

+0

.Net 4,未壓縮爲250MB,一次壓縮一次(不管緩衝區)是411MB,一次壓縮2500次,一次是165MB。 – user7116

+0

謝謝你的建議。但它沒有幫助。緩衝區較大的結果大致相同(517MB - 我也更改了數組的內容以加速實驗)。你的例子中使用的名稱fs也有問題 - fs是BinnaryFormatter(這是我的錯,我使用的fs和cmp名稱令人困惑)。 – danatel

+0

@danatel:我的錯誤。我把緩衝區放在錯誤的一端。看到我使用'BufferedStream'的修正。 –

3

無論出於何種原因,在對.Net中的GZip實現進行快速閱讀期間,這並不明顯,性能對一次寫入的數據量非常敏感。我將您的代碼與幾種寫入GZipStream的代碼進行了基準測試,發現最有效的版本寫入磁盤的時間很長。

權衡在這種情況下的內存,因爲你需要轉換的short[,]基於步幅byte[]你想:

using (var writer = new GZipStream(File.Create("compressed.gz"), 
            CompressionMode.Compress)) 
{ 
    var bytes = new byte[data.GetLength(1) * 2]; 
    for (int ii = 0; ii < data.GetLength(0); ++ii) 
    { 
     Buffer.BlockCopy(data, bytes.Length * ii, bytes, 0, bytes.Length); 
     writer.Write(bytes, 0, bytes.Length); 
    } 

    // Random data written to every other 4 shorts 
    // 250,000,000 uncompressed.dat 
    // 165,516,035 compressed.gz (1 row strides) 
    // 411,033,852 compressed2.gz (your version) 
} 
+0

感謝您的建議。我不知道你用什麼陣列內容作爲基準。我的內容非常有規律,可以壓縮到8MB。 165MB太多了。 – danatel

+0

'data [ii,jj] = random.Next()'爲數據的一半(〜125MB)。我只是一次性地指出了使用1-short與1-row的壓縮差異。 – user7116

+0

這就解釋了這種差異 - 隨機噪聲不像我的常規數據那樣可壓縮。感謝您的幫助。 – danatel