gpt4 book ai didi

c# - 解压缩一个非常大的序列化对象并管理内存

转载 作者:太空宇宙 更新时间:2023-11-03 16:53:36 24 4
gpt4 key购买 nike

我有一个包含大量用于报告的数据的对象。为了从服务器到客户端获取这个对象,我首先在内存流中序列化对象,然后使用.NET 的 Gzip 流压缩它。然后,我将压缩后的对象作为 byte[] 发送给客户端。

问题出在某些客户端上,当他们获取 byte[] 并尝试解压缩和反序列化对象时,会抛出 System.OutOfMemory 异常。我读到这个异常可能是由 new() 一堆对象或持有一堆字符串引起的。这两者都发生在反序列化过程中。

所以我的问题是:如何防止异常(任何好的策略)?客户需要所有的数据,我已经尽可能地减少了字符串的数量。

编辑:这是我用来序列化/压缩的代码(作为扩展方法实现)

public static byte[] SerializeObject<T>(this object obj, T serializer) where T: XmlObjectSerializer
{
Type t = obj.GetType();

if (!Attribute.IsDefined(t, typeof(DataContractAttribute)))
return null;

byte[] initialBytes;

using (MemoryStream stream = new MemoryStream())
{
serializer.WriteObject(stream, obj);
initialBytes = stream.ToArray();
}

return initialBytes;
}

public static byte[] CompressObject<T>(this object obj, T serializer) where T : XmlObjectSerializer
{
Type t = obj.GetType();

if(!Attribute.IsDefined(t, typeof(DataContractAttribute)))
return null;

byte[] initialBytes = obj.SerializeObject(serializer);

byte[] compressedBytes;

using (MemoryStream stream = new MemoryStream(initialBytes))
{
using (MemoryStream output = new MemoryStream())
{
using (GZipStream zipper = new GZipStream(output, CompressionMode.Compress))
{
Pump(stream, zipper);
}

compressedBytes = output.ToArray();
}
}

return compressedBytes;
}

internal static void Pump(Stream input, Stream output)
{
byte[] bytes = new byte[4096];
int n;
while ((n = input.Read(bytes, 0, bytes.Length)) != 0)
{
output.Write(bytes, 0, n);
}
}

这是我的解压缩/反序列化代码:

public static T DeSerializeObject<T,TU>(this byte[] serializedObject, TU deserializer) where TU: XmlObjectSerializer
{
using (MemoryStream stream = new MemoryStream(serializedObject))
{
return (T)deserializer.ReadObject(stream);
}
}

public static T DecompressObject<T, TU>(this byte[] compressedBytes, TU deserializer) where TU: XmlObjectSerializer
{
byte[] decompressedBytes;

using(MemoryStream stream = new MemoryStream(compressedBytes))
{
using(MemoryStream output = new MemoryStream())
{
using(GZipStream zipper = new GZipStream(stream, CompressionMode.Decompress))
{
ObjectExtensions.Pump(zipper, output);
}

decompressedBytes = output.ToArray();
}
}

return decompressedBytes.DeSerializeObject<T, TU>(deserializer);
}

我传递的对象是一个包装器对象,它只包含保存数据的所有相关对象。对象的数量可能很多(取决于报告日期范围),但我看到多达 25k 个字符串。

我忘记提及的一件事是我使用的是 WCF,并且由于内部对象是通过其他 WCF 调用单独传递的,所以我使用的是 DataContract 序列化程序,并且我的所有对象都标有 DataContract 属性。

最佳答案

您可以尝试的一件事是 pre-generating the XmlSerializer assemblies在客户端,如果您还没有这样做的话。

.NET 实际上在运行时生成这些,除非您预先生成并链接到它们。

更多:Sgen.exe更多关于 StackOverflow .

关于c# - 解压缩一个非常大的序列化对象并管理内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3026294/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com