C# 如何使用gzip压缩.net对象实例
在将查询结果添加到缓存之前,我希望压缩来自数据库查询的结果 我希望能够压缩任何引用类型 我有一个压缩字符串的工作版本。。这个想法是基于scott hanselman的博客文章 有压缩.net对象的想法吗C# 如何使用gzip压缩.net对象实例,c#,.net,asp.net,caching,compression,C#,.net,Asp.net,Caching,Compression,在将查询结果添加到缓存之前,我希望压缩来自数据库查询的结果 我希望能够压缩任何引用类型 我有一个压缩字符串的工作版本。。这个想法是基于scott hanselman的博客文章 有压缩.net对象的想法吗 我知道它将是一个只读缓存,因为缓存中的对象将只是字节数组。这不适用于任何引用类型。这将适用于可序列化的类型。将BinaryFormatter连接到通过管道传输到文件的压缩流: var formatter = new BinaryFormatter(); using (var outputFile
我知道它将是一个只读缓存,因为缓存中的对象将只是字节数组。这不适用于任何引用类型。这将适用于可序列化的类型。将
BinaryFormatter
连接到通过管道传输到文件的压缩流:
var formatter = new BinaryFormatter();
using (var outputFile = new FileStream("OutputFile", FileMode.CreateNew))
using (var compressionStream = new GZipStream(
outputFile, CompressionMode.Compress)) {
formatter.Serialize(compressionStream, objToSerialize);
compressionStream.Flush();
}
您可以使用
MemoryStream
将内容保存在内存中,而不是写入文件。但是,我怀疑这是否真的是缓存的有效解决方案。您将什么类型的对象放入缓存?它们是类型化对象吗?或者类似于数据表
?对于DataTable
,则可能存储为通过GZipStream
压缩的xml。对于类型化(实体)对象,可能需要序列化它们
您可以使用
BinaryFormatter
和GZipStream
,或者您可以使用类似序列化(免费)的东西,它已经非常紧凑(添加GZipStream
通常会使数据变大,这是密集二进制文件的典型特征)。特别是,protobuf-net之类的东西的优点是,在反序列化过程中,您不必支付解压缩的CPU成本,就可以获得较小的大小。在添加GZipStream
之前,它比BinaryFormatter
快4倍。将额外的时间添加到GZip的BinaryFormatter上,它将以相当大的优势获胜。我今天刚刚为我的应用程序添加了GZipStream支持,所以我可以在这里分享一些代码
序列化:
using (Stream s = File.Create(PathName))
{
RijndaelManaged rm = new RijndaelManaged();
rm.Key = CryptoKey;
rm.IV = CryptoIV;
using (CryptoStream cs = new CryptoStream(s, rm.CreateEncryptor(), CryptoStreamMode.Write))
{
using (GZipStream gs = new GZipStream(cs, CompressionMode.Compress))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(gs, _instance);
}
}
}
using (Stream s = File.OpenRead(PathName))
{
RijndaelManaged rm = new RijndaelManaged();
rm.Key = CryptoKey;
rm.IV = CryptoIV;
using (CryptoStream cs = new CryptoStream(s, rm.CreateDecryptor(), CryptoStreamMode.Read))
{
using (GZipStream gs = new GZipStream(cs, CompressionMode.Decompress))
{
BinaryFormatter bf = new BinaryFormatter();
_instance = (Storage)bf.Deserialize(gs);
}
}
}
反序列化:
using (Stream s = File.Create(PathName))
{
RijndaelManaged rm = new RijndaelManaged();
rm.Key = CryptoKey;
rm.IV = CryptoIV;
using (CryptoStream cs = new CryptoStream(s, rm.CreateEncryptor(), CryptoStreamMode.Write))
{
using (GZipStream gs = new GZipStream(cs, CompressionMode.Compress))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(gs, _instance);
}
}
}
using (Stream s = File.OpenRead(PathName))
{
RijndaelManaged rm = new RijndaelManaged();
rm.Key = CryptoKey;
rm.IV = CryptoIV;
using (CryptoStream cs = new CryptoStream(s, rm.CreateDecryptor(), CryptoStreamMode.Read))
{
using (GZipStream gs = new GZipStream(cs, CompressionMode.Decompress))
{
BinaryFormatter bf = new BinaryFormatter();
_instance = (Storage)bf.Deserialize(gs);
}
}
}
注意:如果您使用CryptoStream,以这种方式链接(取消)压缩和(取消)加密是非常重要的,因为您希望在加密从数据中产生噪声之前丢失熵。这是如何做到的 GzipStream:提供用于压缩和解压缩流的方法和属性 使用binaryformatter将对象序列化到内存流,并将memorystream挂接到Gzipstream 要压缩的代码如下所示:
public static byte[] ObjectToCompressedByteArray(object obj)
{
try
{
using (var memoryStream = new System.IO.MemoryStream())
{
using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress))
{
var binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(gZipStream, obj);
}
return memoryStream.ToArray();
}
}
catch (Exception ex)
{
LoggerWrapper.CMLogger.LogMessage(
$"EXCEPTION: BSExportImportHelper.ObjectToByteArray - : {ex.Message}", LoggerWrapper.CMLogger.CMLogLevel.Error);
throw;
}
}
谢谢你这真的很有帮助,减压是什么样子的。。。以前从未使用过BinaryFormatter。感谢您将此内容轻松复制到我的代码中。我经常格式化东西,现在这只是一个我可以在谷歌上轻松找到的片段+1.