Wie serialisieren / deserialisieren große Liste von Elementen mit Protobuf-Net

8

Ich habe eine Liste von etwa 500 Millionen Artikeln. Ich bin in der Lage, dies in eine Datei mit protobuf-net-Datei zu serialisieren, wenn ich einzelne Artikel serialisieren, keine Liste - ich kann die Artikel nicht in die Liste der Preise sammeln und dann serialisieren, weil mir der Speicher ausgeht. Also muss ich jeweils einen Datensatz serialisieren:

%Vor%

Meine Frage betrifft den Deserialisierungsteil. Es scheint, dass die Deserialize-Methode die Position des Streams nicht in den nächsten Datensatz verschiebt. Ich habe es versucht:

%Vor%

Ich sehe einen wirklich aussehenden Preisdatensatz, und der Rest sind leere Datensätze - ich bekomme das Price-Objekt zurück, aber alle Felder werden auf die Standardwerte initialisiert.

Wie wird ein Stream richtig deserialisiert, der eine Liste von Objekten enthält, die nicht als Liste serialisiert sind?

    
user1044169 25.11.2011, 17:18
quelle

3 Antworten

4

Gute Nachrichten! Die protobuf-net API ist für genau dieses Szenario eingerichtet. Sie sollten ein Paar Methoden von SerializeItems und DeserializeItems sehen, die mit IEnumerable<T> arbeiten und sowohl Ein- als auch Ausblendungen zulassen. Der einfachste Weg, um es zu nummerieren, ist über einen "Iterator Block" über die Quelldaten.

Wenn dies aus irgendeinem Grund nicht praktisch ist, ist das 100% identisch mit der Verwendung von SerializeWithLengthPrefix und DeserializeWithLengthPrefix für jedes Element, wobei (als Parameter) field: 1 und prefix-style: base-128 angegeben werden. Sie könnten sogar SerializeWithLengthPrefix für das Schreiben und DeserializeItems für das Lesen verwenden (solange Sie field 1 und base-128 verwenden).

Für das Beispiel - id muss das in einem vollständig reproduzierbaren Szenario zu kommentieren; Tatsächlich würde ich erwarten , dass Sie nur ein einzelnes Objekt zurückbekommen, das die kombinierten Werte von jedem Objekt enthält - denn ohne das length-Präfix geht die protobuf spec davon aus, dass Sie nur Werte verketten ein einzelnes Objekt. Die beiden oben genannten Ansätze vermeiden dieses Problem.

    
Marc Gravell 25.11.2011, 18:21
quelle
2

Vielleicht bin ich zu spät dran ... aber ich möchte nur hinzufügen, was Marc bereits gesagt hat.

Wenn Sie Serializer.Serialize(output, price); protobuf verwenden, behandeln Sie aufeinanderfolgende Nachrichten als Teil eines (gleichen) einzelnen Objekts. Wenn Sie also Deserialize verwenden, verwenden Sie

%Vor%

Sie werden alle Datensätze zurückbekommen. Daher sehen Sie nur den letzten Preisdatensatz.

Um zu tun, was Sie tun möchten, ändern Sie den Serialisierungscode in:

%Vor%

und

%Vor%     
Vic 07.05.2013 23:25
quelle
0

Der API-Lehrling hat sich seit Marc's Antwort verändert.
Es scheint, dass es keine SerializeItems-Methode mehr gibt.

Hier sind einige aktuelle Informationen, die helfen sollten:

%Vor%

kann ein IEnumerable wie oben gesehen nehmen und es macht den Job, wenn es um die Serialisierung geht.
Allerdings gibt es eine DeserializeItems (...) Methode und der Teufel steckt im Detail :)
Wenn Sie IEnumerable wie oben beschrieben serialisieren, müssen Sie DeserializeItems aufrufen, indem Sie PrefixStyle.Base128 und 1 als fieldNumber übergeben, da dies die Standardwerte sind.
Hier ist ein Beispiel:

%Vor%

Wie auch von Marc und Vic ausgeführt, können Sie auf einer solchen Basis serialisieren / deserialisieren (indem Sie benutzerdefinierte Werte für PrefixStyle und fieldNumber verwenden):

%Vor%

und

%Vor%     
Piotr Owsiak 20.02.2017 14:01
quelle

Tags und Links