Mar*_*rek 10 c# serialization gzipstream .net-3.5
我在内存中有一个大对象,我想将其作为blob保存到数据库中.我想在保存之前压缩它,因为数据库服务器通常不是本地的.
这就是我现在所拥有的:
using (var memoryStream = new MemoryStream())
{
using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(gZipStream, obj);
return memoryStream.ToArray();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我使用Total Commander压缩相同的字节时,它至少会减小50%的大小.使用上面的代码,它压缩58MB到48MB,任何小于15MB的东西都会变得更大.
我应该使用第三方zip库还是有更好的方法在.NET 3.5中执行此操作.我问题的其他任何替代方案?
编辑:
刚刚在上面的代码中发现了一个错误.安吉洛感谢你的解决.
GZipStream压缩仍然不是很好.与TC 48%压缩相比,gZipStream的平均压缩率为35%.
我不知道我用以前的版本得到了什么样的字节:)
EDIT2:
我发现如何将压缩率从20%提高到47%.我不得不使用两个内存流而不是一个!谁能解释为什么会这样呢?
这是一个包含2个内存流的代码,它可以提供更好的压缩效果!
using (MemoryStream msCompressed = new MemoryStream())
using (GZipStream gZipStream = new GZipStream(msCompressed, CompressionMode.Compress))
using (MemoryStream msDecompressed = new MemoryStream())
{
new BinaryFormatter().Serialize(msDecompressed, obj);
byte[] byteArray = msDecompressed.ToArray();
gZipStream.Write(byteArray, 0, byteArray.Length);
gZipStream.Close();
return msCompressed.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
Joã*_*elo 13
您的代码中存在错误,并且对于评论的解释时间太长,所以即使它没有回答您的真实问题,我也会将其作为答案呈现.
您memoryStream.ToArray()只需在关闭后调用,GZipStream否则您将创建无法反序列化的压缩数据.
固定代码如下:
using (var memoryStream = new System.IO.MemoryStream())
{
using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(gZipStream, obj);
}
return memoryStream.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
将GZipStream在块的基础缓冲区,也写入追加页脚流的结束,这只是在你关闭该流的时刻进行的.
您可以通过运行以下代码示例轻松证明这一点:
byte[] compressed;
int[] integers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var mem1 = new MemoryStream();
using (var compressor = new GZipStream(mem1, CompressionMode.Compress))
{
new BinaryFormatter().Serialize(compressor, integers);
compressed = mem1.ToArray();
}
var mem2 = new MemoryStream(compressed);
using (var decompressor = new GZipStream(mem2, CompressionMode.Decompress))
{
// The next line will throw SerializationException
integers = (int[])new BinaryFormatter().Deserialize(decompressor);
}
Run Code Online (Sandbox Code Playgroud)
小智 2
.NET 3.5 中的 GZipStream 不允许您设置压缩级别。这个参数是在.NET 4.5中引入的,但我不知道它是否会给你更好的结果或者升级是否适合你。由于专利的原因,内置算法并不是非常理想。因此,在 3.5 中,获得更好压缩的唯一方法是使用第三方库,例如7zip或SharpZipLib提供的SDK。也许您应该尝试使用不同的库来更好地压缩数据。