仅反序列化数组的前x个项

时间:2009-06-11 09:27:05

标签: c# .net arrays serialization

是否可以仅从序列化数组中反序列化有限数量的项目?

背景:

我有一个流,它包含一个类型为T的序列化数组。该数组可以有数百万个项目,但我想创建内容的预览,只检索前100个项目。我的第一个想法是在输入流周围创建一个限制字节数的包装器,但是没有从数组的项目数到流大小的直接转换。

3 个答案:

答案 0 :(得分:1)

不,使用标准.NET序列化无法做到这一点。您必须创建自己的存储格式。例如,包括带有数据块偏移量的标头:

----------------
<magic-value>
<chunks-count>
<chunk-size>
<chunk-1-offset>
<chunk-2-offset>  --+
...                 |
----------------    |
...                 |
<chunk-1>           |
...                 |
----------------    |
...               <-+
<chunk-2>
...
-----------------
...

因此,为了预览数据(来自任意位置),您最多只需加载ceil(required-item-count/chunk-size)。这会产生一些开销,但它比加载整个文件要好得多。

答案 1 :(得分:1)

什么是序列化器?

使用BinaryFormatter,这将非常非常棘手。

使用xml,你可以预先处理xml,但这非常棘手。

但是存在其他序列化程序 - 例如,使用protobuf-net,数组/项目列表与单个项目序列之间几乎没有区别 - 因此,选择有限序列的项目非常容易处理整个阵列。


完成protobuf-net示例:

[ProtoContract]
class Test {
    [ProtoMember(1)]
    public int Foo { get; set; }
    [ProtoMember(2)]
    public string Bar { get; set; }

    static void Main() {
        Test[] data = new Test[1000];
        for (int i = 0; i < 1000; i++) {
            data[i] = new Test { Foo = i, Bar = ":" + i.ToString() };
        }
        MemoryStream ms = new MemoryStream();
        Serializer.Serialize(ms, data);
        Console.WriteLine("Pos after writing: " + ms.Position); // 10760
        Console.WriteLine("Length: " + ms.Length); // 10760
        ms.Position = 0;
        foreach (Test foo in Serializer.DeserializeItems<Test>(ms,
                PrefixStyle.Base128, Serializer.ListItemTag).Take(100)) {
            Console.WriteLine(foo.Foo + "\t" + foo.Bar);
        }
        Console.WriteLine("Pos after reading: " + ms.Position); // 902

    }
}

请注意DeserializeItems<T>是一个惰性/流式API,所以它只会在迭代时使用流中的数据 - 因此LINQ Take(100)会避免我们读取整个流。

答案 2 :(得分:0)

您是否可以更改数据源,使其包含另一个数组中的数据预览,您可以单独反序列化?