我在内存中有一个大对象,我想将其作为 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();
}
}
然而,当我使用 Total Commander 压缩相同的字节时,它总是至少将大小减少 50%。使用上面的代码,它将 58MB 压缩到 48MB,任何小于 15MB 的东西都会变得更大。
我应该使用第三方 zip 库还是在 .NET 3.5 中有更好的方法? 我的问题还有其他替代方案吗?
编辑:
刚刚在上面的代码中发现了一个错误。 Angelo 感谢您的修复。
GZipStream 压缩仍然不是很好。 与 TC 48% 的压缩率相比,我通过 gZipStream 获得了平均 35% 的压缩率。
我不知道我从以前的版本中得到了什么样的字节:)
编辑 2:
我发现了如何将压缩率从 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();
}
最佳答案
您在您的代码中有一个错误,并且解释太长而无法发表评论,所以我将其作为答案提供,即使它没有回答您的真正问题。
您需要仅在关闭GZipStream
后调用memoryStream.ToArray()
,否则您将创建无法压缩的数据反序列化。
固定代码如下:
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();
}
GZipStream
以 block 的形式写入底层缓冲区,并将页脚附加到流的末尾,这仅在您关闭流时执行。
您可以通过运行以下代码示例轻松证明这一点:
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);
}
关于c# - 如何在没有第三方库的情况下序列化对象+压缩然后解压+反序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12088623/