gpt4 book ai didi

c# - 复杂 .Net 对象图的快速读/写

转载 作者:太空狗 更新时间:2023-10-30 01:28:18 24 4
gpt4 key购买 nike

我有自己的用 C# 编写的数据结构(结构相当复杂)。我需要序列化和反序列化结构。磁盘中序列化文件的大小有时可能非常大(接近 1 GB),但也可能很小(基于存储的记录数)。我有以下要求:

  1. 序列化和反序列化应该非常快
  2. 我应该能够部分反序列化一个大文件(即只访问一些相关记录),因为如果我从磁盘反序列化整个文件,内存使用率会太高。
  3. 应该是线程安全的,因为多个进程可以从文件写入/读取记录

我知道这听起来像是我需要一个数据库,但由于多种原因我不能使用它。我尝试通过实现 ISerializable 来满足要求 1,这使得它比使用内置在二进制/XML 序列化程序中的 .net 快得多,但速度不够快。因为要求 2 完全难住了我。

有人知道如何解决这个问题吗?我认为任何不得不保存自己的大文件格式的人都必须处理类似的问题。

问候,山姆

最佳答案

是数据,还是完整的 - 即是否有任何循环引用?如果没有,protobuf-net是一个高性能的二叉序列化器。它支持可枚举项目的流式传输(因此您可以跳过记录等 - 而不是缓冲所有内容),但要高效寻找随机元素,我希望您需要某种索引。

读取/写入单个文件非常困难;特别是,写入可能需要移动比您预期更多的磁盘……读取也很棘手,可能需要同步。使用单独的文件会更容易......


跳过早期项目的例子;我可能会添加一个辅助方法,但是 TryDeserializeWithLengthPrefix 方法会起作用...关键是要注意在序列化和反序列化之间我们只创建一个额外的对象。

using System;
using System.IO;
using System.Threading;
using ProtoBuf;

[ProtoContract]
class Foo {
static int count;
public static int ObjectCount { get { return count; } }
public Foo() { // track how many objects have been created...
Interlocked.Increment(ref count);
}
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public double Bar { get; set; }
}
static class Program {
static void Main() {
MemoryStream ms = new MemoryStream();
Random rand = new Random();
for (int i = 1; i <= 5000; i++) {
Foo foo = new Foo { Bar = rand.NextDouble(), Id = i };
Serializer.SerializeWithLengthPrefix(ms, foo,PrefixStyle.Base128, 1);
}
ms.Position = 0;
// skip 1000
int index = 0;
object obj;
Console.WriteLine(Foo.ObjectCount);
Serializer.NonGeneric.TryDeserializeWithLengthPrefix(
ms, PrefixStyle.Base128,
tag => ++index == 1000 ? typeof(Foo) : null, out obj);
Console.WriteLine(Foo.ObjectCount);
Console.WriteLine(((Foo)obj).Id);
}
}

关于c# - 复杂 .Net 对象图的快速读/写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/950471/

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