2011-09-28 16 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