Десериализация только первых x объектов массива

Чтобы получить имя процесса с идентификатором процесса, скажем, 9000, используйте эту команду:

ps -p 9000 -o comm=
1
задан Rauhotz 11 June 2009 в 09:27
поделиться

3 ответа

Нет, это невозможно сделать с помощью стандартной сериализации .NET. Вам придется изобрести собственный формат хранения. Например, включите заголовок со смещениями блоков данных:

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

Таким образом, для предварительного просмотра данных (из любой произвольной позиции) вам нужно будет загрузить не более ceil (required-item-count / chunk-size) . Это повлечет за собой некоторые накладные расходы, но это намного лучше, чем загрузка всего файла.

1
ответ дан 3 September 2019 в 01:28
поделиться

Не могли бы вы изменить свой источник данных, чтобы он содержал предварительный просмотр данных в другом массиве, который можно десериализовать отдельно?

0
ответ дан 3 September 2019 в 01:28
поделиться

Что такое сериализатор?

С 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 является ленивым / потоковым API, поэтому он потребляет только данные из потока при итерации по нему - следовательно, LINQ Take (100) позволяет избежать чтения всего потока.

1
ответ дан 3 September 2019 в 01:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: