【问题标题】:How should I serialize an object containing a large list of objects?我应该如何序列化包含大量对象的对象?
【发布时间】:2015-10-30 09:33:44
【问题描述】:

我正在使用 c# 和 .net 4.5。

我有一个类 SomeData,它包含一个成员 _SomeEvents,它是一个字典。 SomeData 类还包含一堆信息,例如生成数据的时间、生成数据的用户等。

我正在尝试使用 formatter.Serialize 将 SomeData 对象保存到文件,但是当对象很大(例如 1GB)时遇到 OutOfMemoryException

IFormatter formatter = new BinaryFormatter();
Stream stream;
stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, _myObject);
stream.Close();

我读过的其他帖子表明,内存不足问题是由于无法找到足够大的连续可用内存区域来生成要写入磁盘的数据。我还读到这是一种“错误”的序列化方式——我的假设是,如果我做得正确,CLR 会随时写入数据,而不是在保存之前尝试在内存中准备所有数据。也就是说 - 我确实看到在序列化操作失败之前创建了一个大文件,这意味着它正在写入。

我尝试更改序列化操作以编写 Dictionary 对象本身而不是包含 Dictionary 的对象 - 同样的问题,我得到内存异常。

问题:

  1. 为什么 Serialize 会遇到这个内存问题 - 即使我给它一个 Dictionary 对象来序列化 - 它肯定会按原样写入?
  2. 有更好的方法吗?!!

这是完整的例外:

无法保存文件:System.OutOfMemoryException:引发了“System.OutOfMemoryException”类型的异常。

在 System.Runtime.Serialization.ObjectIDGenerator.Rehash()

在 System.Runtime.Serialization.ObjectIDGenerator.GetId(Object obj, Boolean& firstTime)

在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.InternalGetId(Object obj, Boolean assignUniqueIdToValueType, Type type, Boolean& isNew)

在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteString(NameInfo memberNameInfo, NameInfo typeNameInfo, Object stringObject)

在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo, Object data)

在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteMembers(NameInfo memberNameInfo, NameInfo memberTypeNameInfo, Object memberData, WriteObjectInfo objectInfo, NameInfo typeNameInfo, WriteObjectInfo memberObjectInfo)

在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteMemberSetup(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String memberName, Type memberType, Object memberData, WriteObjectInfo memberObjectInfo)

在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String[] memberNames, Type[] memberTypes, Object[] memberData, WriteObjectInfo[] memberObjectInfos)

在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)

在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)

在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)

在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)

【问题讨论】:

标签: c# .net serialization clr


【解决方案1】:

使用流序列化每个对象。看一个例子: 注意:这只是一个模板而不是完整的代码。我只是想给你一个想法。

private void SerializeObjects(List<foo> foos, Stream stream)
{
    foreach (var f in foos)
    {
        stream.Write(f);
    }
}

private void DeserializeObjects(List<foo> foos, Stream stream)
{
    foo f = stream.ReadFoo();
    while (f != null)
    {
        foos.Add(f);
        f = stream.ReadFoo();
    }
}

【讨论】:

  • 我的 SerializeObjects 工作正常,但什么是 stream.ReadFoo(); ?我必须自己写的方法?
  • ReadFoo 只是一个示例,因为您可以通过多种方式阅读。只需从流中使用您需要的读取。请参阅流类。我会说 MemoryStream 是你必须序列化和反序列化的东西
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-01
  • 2014-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多