3 Stimmen

Prozessiere sehr große XML-Datei

Ich muss eine XML-Datei mit folgender Struktur verarbeiten:

Das -Element ist besonders, da es innerhalb des -Elements wiederholt wird, aber auch in sich selbst erscheinen kann; Ich schätze bis zu etwa 5 Ebenen.

Das Problem ist, dass die Datei mit riesigen 11 GB wirklich groß ist, sodass ich Schwierigkeiten habe, sie zu verarbeiten - Ich habe Erfahrung mit XML-Dokumenten, aber nichts in diesem Ausmaß.

Was ich gerne machen würde, ist die Informationen in eine SQL-Datenbank zu importieren, denn dann kann ich die Informationen auf jede erforderliche Weise verarbeiten, ohne mich mit dieser immensen, unpraktischen Datei befassen zu müssen.

Hier sind die Dinge, die ich ausprobiert habe:

  • Einfach die Datei laden und versuchen, sie mit einem einfachen C#-Programm unter Verwendung eines XmlDocument- oder XDocument-Objekts zu verarbeiten
    • Bevor ich überhaupt anfing, wusste ich, dass dies nicht funktionieren würde, wie ich sicher bin, dass jeder zustimmt, aber ich habe es trotzdem versucht und die Anwendung auf einer VM (da mein Notebook nur 4 GB RAM hat) mit 30 GB Speicher ausgeführt. Die Anwendung hat am Ende 24 GB Speicher verwendet und sehr, sehr lange gedauert, also habe ich sie einfach abgebrochen.
  • Versuch, die Datei mit einem XmlReader-Objekt zu verarbeiten
    • Dieser Ansatz funktionierte besser, da er nicht so viel Speicher benötigte, aber ich hatte trotzdem ein paar Probleme:
      • Es dauerte wirklich lange, weil ich die Datei zeilenweise gelesen habe.
      • Die Datei zeilenweise zu verarbeiten, macht es schwierig, wirklich mit den in der XML enthaltenen Daten zu arbeiten, da Sie jetzt den Beginn eines Tags, und dann das Ende dieses Tags (hoffentlich) erkennen und dann ein Dokument aus diesen Informationen erstellen, die Informationen lesen, versuchen, zu bestimmen, zu welchem Elternelement es gehört, weil wir mehrere Ebenen haben... Klingt anfällig für Probleme und Fehler
      • Habe ich erwähnt, dass das Lesen der Datei zeilenweise wirklich lange dauert, und das alles ohne tatsächlich diese Zeile zu verarbeiten - buchstäblich nur lesen.
  • Importieren der Informationen mit SQL Server
    • Ich habe eine gespeicherte Prozedur mit XQuery erstellt und rekursiv in sich selbst ausgeführt, um die -Elemente zu verarbeiten. Das lief ziemlich gut - Ich denke, besser als die anderen beiden Ansätze - bis eines der -Elemente ziemlich groß wurde und einen Einen XML-Vorgang ausgeführt, der einen XML-Datentyp mit einer Größe von mehr als 2 GB verursachte. Vorgang abgebrochen. Fehler produzierte. Ich habe darüber gelesen und glaube nicht, dass es eine anpassbare Grenze gibt.

Hier sind weitere Dinge, die ich versuchen sollte:

  • Meine C#-Anwendung umschreiben, um nicht verwalteten Code zu verwenden
    • Ich habe nicht viel Erfahrung mit nicht verwaltetem Code, daher bin ich mir nicht sicher, wie gut es funktionieren wird und wie ich es so nicht verwaltet wie möglich machen kann.
    • Ich habe einmal eine kleine Anwendung geschrieben, die mit meiner Webcam funktioniert, das Bild empfangen, die Farben invertieren und es auf ein Panel malen. Die Verwendung von normalem verwaltetem Code hat nicht funktioniert - das Ergebnis waren etwa 2 Bilder pro Sekunde. Das Umschreiben der Farbinvertierungsmethode, um nicht verwalteten Code zu verwenden, hat das Problem gelöst. Deshalb dachte ich, dass nicht verwalteter Code eine Lösung sein könnte.
  • Eher auf C++ als auf C# setzen
    • Nicht sicher, ob dies wirklich eine Lösung ist. Wäre es wirklich besser als C#? Besser als nicht verwaltetes C#?
    • Das Problem hier ist, dass ich bisher noch nicht mit C++ gearbeitet habe, also müsste ich erst einige Dinge über C++ lernen, bevor ich wirklich effizient damit arbeiten kann.

Bevor ich weitergehe, dachte ich, ich würde um einige Ratschläge bitten, um eventuell meine Zeit zu verschwenden.

Vielen Dank im Voraus für Ihre Zeit und Unterstützung.

BEARBEITEN

Bevor ich mit der Verarbeitung der Datei beginne, gehe ich sie durch und prüfe die Größe, um dem Benutzer ein Feedback darüber zu geben, wie lange die Verarbeitung dauern könnte; Ich habe einen Screenshot der Berechnung gemacht:

18 Minuten; 1,67 Mio. Zeilen

Das sind etwa 1500 Zeilen pro Sekunde; wenn die durchschnittliche Zeilenlänge etwa 50 Zeichen beträgt, sind das 50 Bytes pro Zeile, das sind 75 Kilobytes pro Sekunde, für eine 11-GB-Datei sollten etwa 40 Stunden dauern, wenn meine Mathematik stimmt. Aber dies betrifft nur das Durchgehen jeder Zeile. Es verarbeitet die Zeile nicht wirklich oder tut etwas damit, also wenn das beginnt, sinkt die Verarbeitungsrate signifikant.

Dies ist die Methode, die während der Größenberechnung ausgeführt wird:

    private int _totalLines = 0;
    private bool _cancel = false; // auf true gesetzt, wenn die Abbruchtaste geklickt wird

    private void CalculateFileSize()
    {
        xmlStream = new StreamReader(_filePath);
        xmlReader = new XmlTextReader(xmlStream);

        while (xmlReader.Read())
        {
            if (_cancel)
                return;

            if (xmlReader.LineNumber > _totalLines)
                _totalLines = xmlReader.LineNumber;

            InterThreadHelper.ChangeText(
                lblLinesRemaining, 
                string.Format("{0} Zeilen", _totalLines));

            string elapsed = string.Format(
                "{0}:{1}:{2}:{3}",
                timer.Elapsed.Days.ToString().PadLeft(2, '0'),
                timer.Elapsed.Hours.ToString().PadLeft(2, '0'),
                timer.Elapsed.Minutes.ToString().PadLeft(2, '0'),
                timer.Elapsed.Seconds.ToString().PadLeft(2, '0'));

            InterThreadHelper.ChangeText(lblElapsed, elapsed);

            if (_cancel)
                return;
        }

        xmlStream.Dispose();
    }

Immer noch in Bearbeitung, 27 Minuten :(

2voto

radai Punkte 23341

Sie können ein XML als einen logischen Strom von Elementen lesen, anstatt zu versuchen, es zeilenweise zu lesen und selbst wieder zusammenzusetzen. Siehe den Code-Ausschnitt am Ende dieses Artikels

Außerdem wurde Ihre Frage bereits hier gestellt

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X