Langsam beim SAX-Parsen - woran liegts?

G

Ghast

Gast
Hallo,

mein Ziel ist, XML-Dateien zu parsen und daraus neue, nach bestimmten Tags gefilterte XML-Dateien zu erzeugen. Die Dateien können recht groß werden, bisher haben wir eine mit 500 MB, die nur einen Bruchteil der Informationen enthält. Daher hab ich von DOM gleich abgesehen und einen SAX-Parser benutzt. Für das Verarbeiten einer 30-MB-Testdatei braucht das Programm auf meinem Rechner etwas mehr als zwei Minuten.

Eine Bremse ist mir bereits klar: In den meisten startElement()-Aufrufen wird über eine ArrayList iteriert, um zu ermitteln, ob der aktuelle Tag in die Ausgabe soll oder nicht. Die vorher durch Eingaben erzeugte ArrayList enthält die Tags, die gespeichert werden sollen und die for-Schleife bricht erst ab, wenn der aktuelle Tag in der Liste entdeckt wurde oder sie ganz durchgegangen ist.
--> Gibt es hier eine schnellere/bessere Alternative zur ArrayList? Ehrlich gesagt habe ich mich mit Collections und Iterables nicht groß beschäftigt. Die Liste wird dynamisch erstellt, ist aber beim Parsen im Prinzip fest - wäre es besser, sie einfach zu einem regulären Array umzuwandeln?

Das scheint jedoch nicht das einzige Problem zu sein. Kommentiere ich die Listeniteration aus und führe einfach nur einen einfachen Test auf Gleichheit mit einem Dummy-Tag durch, benötigt das Programm dennoch fast eine Minute, um das 30-MB-Dokument zu parsen und die mit dem Dummy identischen Tags rauszuschreiben.

Hier der Parser:

Java:
public class LexParser extends DefaultHandler {

    private Stack <Tag> evaluateTag;
    private int depth;
    private boolean insideTag = false;
    public ArrayList <Tag> selectedTags;
    private StringBuffer xmltext;
    private boolean header;
    
    // ------------------------------------------------------------------------------
    // Parser
    // ------------------------------------------------------------------------------

    public LexParser (File parsefile, ArrayList list) {
        xmltext = new StringBuffer("");
        depth = 0;
        evaluateTag = new Stack ();
        selectedTags = list;
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            // Ignore external DTD
            factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
            // Build and start parser
            SAXParser saxParser = factory.newSAXParser();
            saxParser.parse(parsefile,this);
        }
        catch (ParserConfigurationException e) {
            System.out.println("Configuration error");
            return;
        }
        catch (SAXException e) {
            System.out.println("SAX error " + e.getMessage());
            return;
        }
        catch (IOException e) {
            System.out.println("IO Error " + e.getMessage());
            return;
        }
    }

    public void startDocument() {
    }

    public void endDocument() {
    }

    public void characters(char[] ch, int start, int length) {
        // collect header-characters
        if (header) {
            String text = new String (ch, start, length).replaceAll("\n","").replaceAll("\t","");
            if (!text.equals("")) {
                xmltext.append(text);
            }
        }
        else if ((!evaluateTag.empty()) && (evaluateTag.peek().getDepth() == depth-1)) {
            String text = new String (ch, start, length).replaceAll("\n","").replaceAll("\t","");
            if (!text.equals("")) {
                xmltext.append(text);
            }
            else
                for (int i = 1; i < depth; i++) xmltext.append("\t");
        }
    }

    public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException {
        depth++;

        // header: evaluate completely
        if (qName.equals("teiHeader") || header) {
            header = true;
            xmltext.append("\n");
            for (int i=1; i<depth; i++) xmltext.append("\t");
            // output tags with their attributes
            xmltext.append("<"+qName);
            int attr = attributes.getLength();
            for (int i=0; i<attr; i++) {
                xmltext.append(" "+attributes.getQName(i)+"=\""+attributes.getValue(i)+"\"");
            }
            xmltext.append(">");
        }
        
        // first 4 layers (TEI, text, body, div): always evaluate
        else if (depth<5) {
            for (int i=1; i<depth; i++) xmltext.append("\t");
            // output tags with their attributes
            xmltext.append("<"+qName);
            int attr = attributes.getLength(); 
            for (int i=0; i<attr; i++) {
                xmltext.append(" "+attributes.getQName(i)+"=\""+attributes.getValue(i)+"\"");
            }
            xmltext.append(">\n");
        }

        // inside an evaluated tag: evaluate that tag and its relevant subtags
        else if ((!evaluateTag.empty()) && (evaluateTag.peek().getDepth() == depth-1) && (qName.equals("string")||qName.equals("numeric")||qName.equals("binary")||qName.equals("symbol")) ) {
            insideTag = true;
            xmltext.append("\n");
            for (int i = 1; i < depth; i++) xmltext.append("\t");
            // output tags with their attributes
            xmltext.append("<"+qName);
            int attr = attributes.getLength();
            for (int i=0; i<attr; i++) {
                xmltext.append(" "+attributes.getQName(i)+"=\""+attributes.getValue(i)+"\"");
             }
             xmltext.append(">");
        }
        
        // everything beneath first layer, not inside evaluated tag: evaluate according to user's choice
        else {
            Tag thistag = new Tag(qName,attributes.getValue(0),"",depth);
  
            for (Tag t: selectedTags) {
                if (t.equals(thistag)) {
                    xmltext.append("\n");
                    for (int i = 1; i < depth; i++)
                        xmltext.append("\t");
                    xmltext.append("<"+qName);
                    int attr = attributes.getLength();
                    for (int i=0; i<attr; i++) {
                        xmltext.append(" "+attributes.getQName(i)+"=\""+attributes.getValue(i)+"\"");
                    }
                    xmltext.append(">");
                    evaluateTag.push(thistag);
                    break; // don't look up rest of the list, if already matched 
                }
            }
        }
    }


    public void endElement(String uri,String localName,String qName) throws SAXException {
        
        // close header
        if (header) {
            xmltext.append("\n");
            for (int i=1; i<depth; i++) xmltext.append("\t");
            xmltext.append("</"+qName+">");
            if (qName.equals("teiHeader")) {
                header = false;
                xmltext.append("\n\n");
            }
        }
        
        // close first layers
        else if (depth<5) {
            xmltext.append("\n");
            for (int i=1; i<depth; i++) xmltext.append("\t");
            xmltext.append("</"+qName+">");
        }

        // close selected tags
        else {
            if (!evaluateTag.empty()) {
                Tag thistag = evaluateTag.peek();
                if ((qName.equals(thistag.getTagName())) && (thistag.getDepth()==depth)) {
                    xmltext.append("\n");
                    for (int i = 1; i < depth; i++) xmltext.append("\t");
                    xmltext.append("</"+qName+">\n");
                    evaluateTag.pop();
                }
                if (insideTag) {
                    xmltext.append("</"+qName+">");
                    insideTag = false;
                }   
            }
        }
        
        depth--;
    }

}

Verdächtig in Sachen Tempo finde ich noch den Stack, in dem die zu evaluierenden Tags landen ... aber ich weiß nicht genau, wie sich das eleganter lösen ließe. Der wird in characters(), startElement() und in endElement() abgefragt.

Gibt es irgendwelche auffällige Bremsen in dem Ding? Bisher musste ich zum Glück nie größere Dateien verarbeiten (XML oder sonstige). Aber daher hab ich mich dann auch nicht wirklich mit Performanz im Allgemeinen beschäftigt.
 

parabool

Bekanntes Mitglied
Prüfe das Enthaltensein in der ArrayList mittels contains = einmalige Abfrage pro aktuellen Tag.
HashSet verwenden = noch schneller.
 
G

Ghast

Gast
Wow. Für die contains-Abfrage musste ich die equals- und hashCode-Methoden der Klasse Tag noch einmal formgemäß überschreiben, aber jetzt funktioniert die Abfrage auf dem HashSet wunderbar. Das 30-MB-Dokument wird in knapp 2,5 Sekunden durchlaufen.

Danke!
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
T XML mit JDOM auslesen => langsam? XML & JSON 7
W Ungleiches Escaping beim Marshalling XML & JSON 8
S Hilfe beim RDF-Graphen XML & JSON 0
R Beim Serialisieren fehlt die letzte Zeile XML & JSON 5
N Probleme bei der Formatierung beim Einfügen und löschen über DOM XML & JSON 7
A Leeres Array beim Auslesen von XML-Datei XML & JSON 4
L Jackson JSON: Probleme beim einlesen XML & JSON 1
A XML-Fehler beim Prefix von xmlns XML & JSON 2
K Beim Parsen einer XML-Datei Connection timed out XML & JSON 4
A Fehler beim Erzeugen eines XML-Schema XML & JSON 4
B Validierung nur beim einlesen oder auch beim schreiben? XML & JSON 4
D JAXBException beim Marshaller XML & JSON 4
M Read / write Problem beim ByteStrom XML & JSON 2
whitenexx Problem beim parsen von Facebook XML XML & JSON 3
J Dateinamen beim Start auslesen XML & JSON 8
F Hilfe beim bearbeiten von XML elemente XML & JSON 3
N XStream ConversionException beim Deserialisieren in (Hibernate)Objekt XML & JSON 6
hdi Probleme beim Erstellen einer XML XML & JSON 7
F Probleme beim html parsen mit tagsoup XML & JSON 4
M Probleme beim Parsen eines gefilterten XML-Dokuments XML & JSON 6
G Problem beim schreiben von XML in eine File XML & JSON 2
L Reihenfolge beim xml Datei parsen einhalten? XML & JSON 8
H JAXB Probleme beim Unmarshalling XML & JSON 3
sylo Beim Erzeugen einer XML Datei auch die XML Struktur erzeugen? XML & JSON 11
B Problem beim löschen von ChildNodes aus einem XML-DOM XML & JSON 3
E JDOM - Problem beim Zusammenfügen zweier Dateien XML & JSON 2
N Hilfe beim Einstieg in EMF XML & JSON 6
D Das Programm hängt etwa 5 Sekunden beim Aufruf der parse-Methode XML & JSON 6
D Tabs/Einrückungen der XML-Elemente gehen beim Schreiben verloren XML & JSON 5
T Problem beim Parsen von Attribut xmlns="urn:com:test&qu XML & JSON 6
G XML Tag beim Einlesen manipulieren XML & JSON 2
J Problem beim XML-Lesen XML & JSON 2
S Probleme beim erstellen einer Jar XML & JSON 12
N jdom problem beim lesen von child elementen XML & JSON 5
P NullPointerException beim Auslesen XML & JSON 8
M Performance beim Binding XML & JSON 2
C SAX Probleme beim lesen XML & JSON 4
D Probleme beim SAX parsing XML & JSON 4
E XOM setzen von XML-Schema declaration beim erzeugen XML-File XML & JSON 2
byte Probleme beim Parsen von XHTML-Datei XML & JSON 4
J Fehler beim laden einer .xml XML & JSON 3
G DOCTYPE Problem beim Transformer/TransformerFactory etc. XML & JSON 13
P OutOfMemoryError beim Einlesen einer XML-Datei XML & JSON 7
P Problem beim erstellen eines neuen Elements (JDOM) XML & JSON 5
S JDOM-Kein indent beim XMLOutputter XML & JSON 4
C Zeile herausfinden in der ein Fehler beim Einlesen entsteht XML & JSON 3
V Datenverlust nach sortieren (nur beim serialisieren) XML & JSON 4
S Problem beim Erstellen eines pdfs XML & JSON 3
R Problem beim Auslesen von Attributen XML & JSON 4
R JAVA und DOM, probleme beim einfügen von elementen ?????? XML & JSON 6
MiMa Buch Metadaten aus XML Datei parsen XML & JSON 48
S XML Document Parsen und Ausgeben mit Suchfunktion XML & JSON 21
M parsen von realen HTML-WEB-Seiten XML & JSON 1
MiMa parsen mit regex -> ein schnelles Ende XML & JSON 10
F Parsen von Daten aus einer Homepage XML & JSON 6
C Parsen des XML-Streams mit SAX XML & JSON 3
M XML Datei Parsen XML & JSON 4
D SAX parsen - Wie? XML & JSON 11
S XML Parsen und Werte zwischenspeichern XML & JSON 2
K Kurze XML Datei Parsen XML & JSON 5
J Comments in XML parsen XML & JSON 3
H Nicht wohlgeformtes XML mit SAX parsen XML & JSON 2
M XML Parsen JDOM NullPointerEcxeption XML & JSON 7
Z XML parsen - Element mit Werten XML & JSON 2
ruutaiokwu xml nur bis auf eine bestimmte ebene parsen mit javax.xml... XML & JSON 5
L [SAX] Geschachtelte XML Datei parsen XML & JSON 3
R XML in UTF-8 mit SAX parsen XML & JSON 9
O Parsen einer XML mit JDOM ohne Doctype Declaration XML & JSON 2
Semox Kann JUnit XML Parsen? XML & JSON 2
L xml Datei parsen ohne End-Tag XML & JSON 6
T RSS-Feed parsen und in Datenbank speichern XML & JSON 6
B XML parsen XML & JSON 3
H XML parsen und unbekannten Namespace zurückgeben XML & JSON 5
L invalide xml document parsen?! XML & JSON 2
S DOM Parsen Problem mit HTML Sonderzeichen XML & JSON 4
ABstraCT XML properties am einfachsten parsen. XML & JSON 2
U xmi parsen über emf XML & JSON 10
S XML-Schema einlesen um parsen zu erleichtern? XML & JSON 2
P XMLGregorianCalender parsen XML & JSON 4
M Datei parsen XML & JSON 5
S HTML mit dom4j parsen? XML & JSON 2
X XML File auslesen/parsen u. in ne Hashmap speichern XML & JSON 2
Saxony unbekannte XML Datei parsen und ausgeben XML & JSON 10
P "Formatierungs-Tags" parsen XML & JSON 3
M Attribute parsen XML & JSON 6
R Parsen einer XML ohne Validierung XML & JSON 2
D XML Datei innerhalb einer JAR Datei parsen XML & JSON 2
M Xerces -Parsen mit einer externen Schemadatei geht nicht XML & JSON 2
L bz2-Datei parsen XML & JSON 9
K XML parsen Whitespaces XML & JSON 2
I XML-String mit SAX parsen ? XML & JSON 2
M Object in XML parsen XML & JSON 2
P HTML Seite Parsen, und bestimmten Text extrahieren XML & JSON 3
X xml und xsl parsen mit xerces XML & JSON 8
W Xml-String parsen XML & JSON 2
W root element parsen,Hilfe! XML & JSON 5
F Gibt es Möglichkeiten Deutsche Sätze zu parsen ? XML & JSON 2
A Auf der Suche nach Bibliotheken oder wie parsen? XML & JSON 15
S XML Datei mit Schemafehler parsen XML & JSON 14
R StreamSource parsen ! XML & JSON 8

Ähnliche Java Themen

Neue Themen


Oben