Ich verwende den folgenden Code, um eine lokale ZIP-Datei zu dekomprimieren, die einen komprimierten Json-Feed enthält, der von HttpClient abgerufen wurde.Deserialisieren von Streaming-Daten größer als die Speicherkapazität mit Json.Net
ProgressStream progressStream = null;
API_Json_Special_Feeds.RootObject root = null;
private void import_File(string file)
{
isImporting = true;
Console.WriteLine("Importing " + Path.GetFileName(file));
using (FileStream read = File.OpenRead(file))
{
progressStream = new ProgressStream(read);
using (GZipStream zip = new GZipStream(progressStream, CompressionMode.Decompress))
{
UTF8Encoding temp = new UTF8Encoding(true);
var serializer = new JsonSerializer();
StreamReader sr = new StreamReader(zip);
using (var jsonTextReader = new JsonTextReader(sr))
{
root = serializer.Deserialize<API_Json_Special_Feeds.RootObject>(jsonTextReader);
//I'd like to manipulate root between these lines
foreach (API_Json_Special_Feeds.Item item in root.items)
{
Special_Feed_Data.special_Feed_Items.Add(item);
}
}
progressStream.Dispose();
}
}
}
Die Datei ist ziemlich groß bei 300-600MB komprimiert und 9-11GB unkomprimiert. Wie Sie sehen können, habe ich einen Zwischenstream eingefügt, damit ich den Durchsatz überprüfen kann. Alles funktioniert gut auf meinem 64GB-Computer, aber der Client hat nur 8 GB zu spielen. Der Versuch, 9-11G auf einer Maschine mit 8G RAM zu dekomprimieren und zu serialisieren, wird keinen Spaß machen.
Ich bin neu in Json, so mein ursprünglichen Gedanke war, auf den Daten eine Art Filter oder Paginierung zu setzen, wie es deserialisiert Wesen, vielleicht in der gleichen Methode, die ich verwende Stream-Durchsatz zu messen:
private void timer()
{
bool isRunning = true;
while (isRunning)
{
if (progressStream != null)
{
kBytes_Read = ((double)progressStream.BytesRead/(double)1024);
mem_Used = get_Memory_Used();
if (root != null)
Console.WriteLine("Root contains " + root.items.Count.ToString() + " items");
//This doesn't work, because root is null until ALL of the data is deserialized
}
Thread.Sleep(450);
}
}
In meinem Kopf sehe ich, wie Json.net einen Datensatz nach dem anderen löscht und zur Liste der Elemente in root hinzufügt. Das Problem dabei ist, dass "root" zu null ausgewertet wird, bis der Stream vollständig ist. Ich kann keinen Weg finden, auf die deserialisierten Daten zuzugreifen, bis die Deserialisierung abgeschlossen ist.
Frage Gibt es eine Möglichkeit, auf die Daten zuzugreifen, die bereits in Root.Items serialisiert wurden, während die Deserialisierung noch in Bearbeitung ist? Wenn nicht, wie würde man die Deserialisierung von großen Daten anhalten/paginieren/pausieren, damit sie das Gedächtnis nicht ausreißt?
Ich danke Ihnen für Ihre Zeit und im Voraus für alle Gedanken oder Vorschläge, die Sie zur Verfügung stellen können.
Viel verpflichtet, Evk! In meinem Fall sind die Dateien (es gibt viele) komprimiert. Um dies zu implementieren, müsste ich dann auf das Streaming verzichten, jede Datei lokal dekomprimieren und dann mit dem Textreader lesen? Bitte haben Sie Geduld mit meiner Ignoranz. Ich bin mir sicher, du weißt wie es ist, wenn du zum ersten Mal deinen Fuß in eine neue Technologie steckst. –
@ShannonHolsinger Sie können den JsonTextReader mit jedem TextReader verwenden, wie zum Beispiel dem [StreamReader] (https://msdn.microsoft.com/en-us/library/system.io.streamreader) – ESG
Nein, nein, warten Sie nicht - ich denke ich Bekomme, was du sagst. Anstatt Deserialize zu verwenden, kann ich die String-Filterung wie vorgeschlagen implementieren. Genial. Lass mich versuchen zu implementieren. –