我希望在将数据库查询结果添加到缓存之前对其进行压缩。
我想要能够压缩任何引用类型。
我已经有了一个可以压缩字符串的工作版本。这个想法基于Scott Hanselman的博客文章http://shrinkster.com/173t
有没有关于压缩.NET对象的任何想法?
我知道它将是只读缓存,因为缓存中的对象将只是字节数组。
我希望在将数据库查询结果添加到缓存之前对其进行压缩。
我想要能够压缩任何引用类型。
我已经有了一个可以压缩字符串的工作版本。这个想法基于Scott Hanselman的博客文章http://shrinkster.com/173t
有没有关于压缩.NET对象的任何想法?
我知道它将是只读缓存,因为缓存中的对象将只是字节数组。
这对于任何引用类型都不起作用。这将适用于Serializable类型。连接一个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
将内容保存在内存中,而不是写入文件。然而我怀疑这并不是缓存的有效解决方案。
今天我为我的应用程序添加了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);
}
}
}
注意:如果你使用CryptoStream,非常重要的一点是正确地链接(解)压缩和(解)加密,因为你希望在加密从数据中创建噪声之前消除熵。
DataTable
这样的东西?对于DataTable
,您可以通过GZipStream
压缩为xml进行存储。对于类型化(实体)对象,您可能需要对它们进行序列化。BinaryFormatter
和GZipStream
,也可以使用一些已经非常紧凑的序列化工具,例如protobuf-net(免费)。特别是,像protobuf-net这样的工具的优点是,您可以在反序列化期间不必支付解压缩的CPU成本就能获得减小的数据大小。在添加GZipStream
之前,在某些测试中,它比BinaryFormatter
快4倍。将额外的时间加到BinaryFormatter
上以进行GZip操作,它应该会以相当大的优势获胜。以下是如何完成此操作的方法。
GzipStream:提供用于压缩和解压缩流的方法和属性。
使用binaryformatter将对象序列化到内存流中,并将该内存流连接到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;
}
}