Wie füge ich 1000 xml-Dateien in eine mit Java zusammen

8

Ich versuche, viele XML-Dateien zu einem zusammenzuführen. Ich habe das erfolgreich in DOM gemacht, aber diese Lösung ist auf ein paar Dateien beschränkt. Wenn ich es auf mehrere Dateien & gt; 1000 ausführe bekomme ich einen java.lang.OutOfMemoryError.

Was ich erreichen möchte ist, wo ich die folgenden Dateien habe

Datei 1:

%Vor%

Datei 2:

%Vor%

Datei n:

%Vor%

ergibt: Ausgabe:

%Vor%

Dies ist meine aktuelle Implementierung:

%Vor%

Ich habe viel mit xslt, sax experimentiert, aber ich vermisse immer wieder etwas. Jede Hilfe würde sehr geschätzt werden

    
Andra 25.05.2012, 18:41
quelle

6 Antworten

8

Sie könnten auch StAX in Betracht ziehen. Hier ist Code, der tun würde, was Sie wollen:

%Vor%

Ein kleiner Vorbehalt ist, dass diese API mit leeren Tags zu verwirren scheint, indem <foo/> in <foo></foo> geändert wird.

    
csd 25.05.2012, 19:22
quelle
3

Mach es einfach ohne XML-Analyse, da es kein tatsächliches Parsing der XML-Datei erfordert.

Für Effizienz machen Sie etwas wie folgt:

%Vor%     
quelle
2

DOM muss das gesamte Dokument im Speicher behalten. Wenn Sie mit Ihren Tags keine spezielle Operation ausführen müssen, verwende ich einfach einen InputStream und lese alle Dateien. Wenn Sie einige Operationen ausführen müssen, verwenden Sie SAX.

    
Carlos Tasada 25.05.2012 18:50
quelle
2

Dom verbraucht viel Speicher. Sie haben, imho, die folgenden Alternativen.

Am besten ist es, SAX zu verwenden. Bei Verwendung von sax wird nur eine sehr kleine Menge an Speicher verwendet, da im Grunde genommen fast ein einzelnes Element zu jedem Zeitpunkt von Eingang zu Ausgang läuft, so dass der Speicherbedarf extrem gering ist. Allerdings ist die Verwendung von sax nicht so einfach, denn im Vergleich zu dom ist es ein wenig kontraintuitiv.

Versuchen Sie Stax, nicht versucht, selbst, aber es ist eine Art von Sax auf Steroiden einfacher zu implementieren und zu verwenden, denn im Gegensatz zu nur Sax Veranstaltungen erhalten Sie nicht kontrollieren, Sie tatsächlich "fragen die Quelle", um Sie die Elemente zu streamen Sie wollen, dass es in der Mitte zwischen dom und sax passt, hat einen ähnlichen Speicherbedarf wie Sax, aber ein freundlicheres Paradigma.

Sax, stax, dom sind alle wichtig, wenn Sie Namespaces und andere XML-Merkwürdigkeiten korrekt beibehalten, deklarieren usw. wollen.

Wenn Sie jedoch nur einen schnellen und schmutzigen Weg brauchen, der wahrscheinlich auch namespace-konform ist, sollten Sie einfache alte Strings und Writer verwenden.

Starten Sie die Ausgabe der Deklaration und des Wurzelelements Ihres "großen" Dokuments an den FileWriter. Laden Sie dann, wenn Sie möchten, jede einzelne Datei mit dom. Wählen Sie die Elemente aus, die in der "großen" Datei enden sollen, serialisieren Sie sie in eine Zeichenfolge und senden Sie sie an den Schreiber. Der Writer wird ohne großen Arbeitsspeicher auf die Festplatte geschrieben, und dom lädt nur ein Dokument pro Iteration. Wenn Sie nicht auch sehr große Dateien auf der Eingabeseite haben oder planen, sie auf einem Mobiltelefon auszuführen, sollten Sie nicht viele Speicherprobleme haben. Wenn dom es serialisiert, sollte es Namespace-Deklarationen und ähnliches beibehalten, und der Code wird nur aus einer Reihe von Zeilen bestehen, die größer sind als die, die Sie gepostet haben.

    
Simone Gianni 25.05.2012 19:00
quelle
1

Für diese Art von Arbeit werde ich vorschlagen, DOM nicht zu verwenden, den Dateiinhalt zu lesen und eine Teilzeichenkette einfacher und genug zu machen.

Ich denke an so etwas:

%Vor%

Dann, um zu viel Speicherverbrauch zu vermeiden. Schreiben Sie nach jeder xml-Extraktion mit einer BufferedWritter in die Hauptdatei. Für eine bessere Leistung können Sie auch java.nio .     

alain.janinm 25.05.2012 18:58
quelle
1

Ich denke, was du tust, ist gültig. Der einzige Weg, um es auf eine wirklich große Anzahl von Dateien zu skalieren, ist die Verwendung eines textbasierten Ansatzes mit Streaming, so dass Sie das Ganze nie im Speicher behalten. Aber hey! Gute Nachrichten. Speicher ist in diesen Tagen billig, und 64-Bit-JVMs sind der letzte Schrei, also reicht es vielleicht aus, die Heap-Größe zu erhöhen. Versuchen Sie, Ihr Programm erneut mit einer JVM-Option -Xms1g auszuführen (weist eine 1-Gb-Initial-Heap-Größe zu).

Ich neige auch dazu, XOM für alle meine DOM-Anforderungen zu verwenden. Probieren Sie es aus. Viel effizienter. Ich bin mir nicht sicher über die Speicheranforderungen, aber meiner Erfahrung nach um Größenordnungen schneller.

    
Malcolm Smith 25.05.2012 19:12
quelle