Große XML-Files parsen

LordNikkon

Mitglied
Hi,

ich habe ein Programm geschrieben, welches mir Produkte incl. Staffelpreise etc. anzeigt und zusätzlich eine Suche ermöglicht.
Die Artikel habe ich als XML-Datei vorliegen (SAP-Export). Bisher habe ich immer nur Testweise bestimmte Kataloge verwendet und hatte somit ein ca. 3MB großes XML-File. Jetzt nachdem das Prog fertig ist habe ich alle Artikel geladen und habe jetzt ca 20Mb.
Ich parse das XML-File beim Start des Programms mithilfe von JDOM und lese diese in unterschiedliche Beans ein.
Leider killen die 20MB nun mein System, bekomme die Exception Java.lang.OutOfMemoryError wenn ich mit Hilfe des SAXBuilder die Methode build("XML-File") aufrufe.

Hoffe mir kann jmd ein Tipp geben wie ich das XML-File besser parsen kann?

im vorraus vielen Dank!

Gruß
l|N

Edit:
Habe es einmal so
Code:
builder = new SAXBuilder();
doc = builder.build(getClass().getResource(fileName));
und einmal so probiert
Code:
builder = new SAXBuilder();
BufferedReader is = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(fileName)));
doc = builder.build(is);
Beides hat leider nichts gebracht, wobei beim 2. der BufferedReader einwandfrei durchläuft aber der der builder dann abschmiert.
 
Zuletzt bearbeitet:
Hallo!

Es bestünde die Möglichkeit der Java Laufzeit mittels der Parameter -Xms und -Xmx
mehr Speicher zur Verfügung zu stellen. ZBsp.:
-Xms64m
-Xms256m

Wie verarbeitest du denn das Dokument? "Fasst" du wirklich jedes Element an? Normalerweise verwenden "schlaue" XML Parser die Technik der "deferred Node initialization". Damit werden Objekt-Repräsentationen für XML Elemente erst dann gebaut, wenn wirklich auf das Element zugegriffen wird. Wenn du auf alle Elemente zugreifst solltest du vielleicht deinen Parse-Vorgang "optimieren". Z.Bsp. indem du ElementHandler implementierst welche während des Parsens auf bestimmte Elemente (die die dich interessieren) reagieren und für jedes Element eine Behandlungsroutine aufruft.

Bsp.:

Code:
/**
 * 
 */
package de.tutorials;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

/**
 * @author Tom
 */
public class XMLTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		BufferedWriter bw = new BufferedWriter(new FileWriter("c:/foo.xml"));

		// Dummy XML Datei erstellen:
		// foo.xml -> 36.666.704 foo.xml (~36 MB)

		bw.write("<?xml version=\"1.0\"?>");
		bw.write("<root>");
		for (int i = 0; i < 1000000; i++) {
			bw.write("<element" + i + ">");
			bw.write(String.valueOf(i));
			bw.write("</element" + i + ">");
		}
		bw.write("</root>");
		bw.flush();
		bw.close();

		SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
		parser.parse(new File("c:/foo.xml"), new DefaultHandler() {
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) {
				System.out.print(qName);
				System.out.print(": ");
			}

			public void characters(char[] ch, int start, int length) {
				char[] tmp = new char[length];
				System.arraycopy(ch,start,tmp,0,length);
				System.out.println(new String(tmp));
			}

		});

	}
}

Wenn du nur einen kleinen Ausschnitt aus dem Export benötigst wäre XPath auch recht hilfreich.

Gruß Tom
 
Hi,
danke für deine Antwort, leider fällt Möglichkeit 1 den Parameter xms mitgeben weg, hat ich auch schon daran gedacht.

Ich benötige wirklich alle Elemente, jedoch könnte ich beim parsen zunächst den ersten Teil (Kategorien) des Dokuments abarbeiten und dann den zweiten (Artikel), hier ein kleines Beispiel:

Code:
<?xml version="1.0" encoding="utf-8" ?> 
<BusinessDocument>
     <Catalog>
     
         <CatalogID>Catalog1</CatalogID> 
         <Description Language="DE">Endkunde</Description> 
         <ValidFrom>2002-02-17</ValidFrom> 
         <ValidUntil>9999-12-31</ValidUntil> 
         <DefaultLanguage>DE</DefaultLanguage> 
         
         <Category>
            <CategoryID Code="Seller">KLFO</CategoryID> 
            <Description Language="DE">Kleinformatpapiere A4/A3</Description> 
            <Text Language="DE"><b>Immer die richtige Entscheidung!</b><p> Erleben Sie mit uns gemeinsam die vielfältige Welt der Bürokommuniksationspapiere von Schneidersöhne.<br>Egal für welche Art der Anwendung Sie ein passendes Produkt suchen, die vielfältige Welt von Schneidersöhne hat eine geeignete Lösung für Sie parat. Überzeugen Sie sich selbst!</Text> 
            <Attachment>
              <URL href="http:///3860569828E9714F98D44D2C35E64E74.gif">/3860569828E9714F98D44D2C35E64E74.gif</URL> 
              <MimeType>image/gif</MimeType> 
              <Description Language="DE" /> 
            </Attachment>
            <CategoryAttribute>
              <Key>ZIS_PAARIESINHALT</Key> 
              <Name>Inhalt je Ries</Name> 
            </CategoryAttribute>
            ...54 weitere Attribute
         </Category>
        ....weitere Kategorien....
        
        <Product ProductType="Good">
          <ProductID Code="Seller">30434</ProductID> 
          <ProductKey>3C54ED81D1A5C392E1000000C0A82AA3</ProductKey> 
          <CatalogKey>2F05EDC8590F894BAFC61810A4C5F8CA</CatalogKey> 
          <ParentCategoryID>DIGITAL PRINT</ParentCategoryID> 
          <BasicUnitOfMeasure>TBL</BasicUnitOfMeasure> 
          <Description Language="DE">Color-Copy 200g 21x29,7S weiß</Description> 
          <CatalogText Language="DE">Color Copy - Das multifunktionale Highend-Papier für digitale Topergebnisse! Color Copy ist ein holzfreies, hochweißes Highend-Papier speziell für Farblaserausdrucke und Farbkopien. Color Copy ist satiniert und auch für Inkjetdrucker die richtige Lösung. Unschlagbar in seiner Sortimentstiefe - von Kleinformat bis Großformat alles erhältlich!</CatalogText> 
          <CatalogText Language="DE">Color Copy - 200 g/m², 21x29,7 SB, A4, holzfrei weißes Spezialpapier, geriest (662200)</CatalogText> 
          <Picture>
              <URL href="http:///C5655AD3844CDA40B6E50D838EAD0479.gif">/C5655AD3844CDA40B6E50D838EAD0479.gif</URL> 
              <MimeType>image/gif</MimeType> 
              <Description Language="DE" /> 
          </Picture>
          <Attribute>
              <Key>ZIS_PAARIESINHALT</Key> 
              <Name>Inhalt je Ries</Name> 
              <Value>250</Value> 
          </Attribute>
          ...54 weitere Attribute
        </Product>
        ....weitere Produkte....

</Catalog>
</BusinessDocument>

Nur habe ich das Problem, das ich nicht weiß wie ich zuerst nur die Kategorien und dann die Artikel parsen kann ohne das er gleich beide mitparst?

Danke.
 
Hi,

habs jetzt hinbekommen, klappt auch mit noch größeren Files. Danke für die Hilfe!
Es lag eindeutig am SAXBuilder, glaube das dieser nicht mit so großen Files umgehen kann, mithilfe des SAXParsers war es kein Problem.

Gruß
l|N
 
Zurück