Ich schreibe einen SAX-Parser in Java, um eine 2,5 GB XML-Datei von Wikipedia-Artikeln zu analysieren. Gibt es eine Möglichkeit, den Fortschritt des Parsens in Java zu überwachen?Java SAX Parser Fortschrittsüberwachung
Antwort
Verwenden Sie ein javax.swing.ProgressMonitorInputStream.
Angenommen, Sie wissen, wie viele Artikel Sie haben, können Sie nicht einfach einen Zähler im Handler behalten? Z.B.
public void startElement (String uri, String localName,
String qName, Attributes attributes)
throws SAXException {
if(qName.equals("article")){
counter++
}
...
}
(ich weiß nicht, ob Sie „Artikel“ parsen, es ist nur ein Beispiel)
Wenn Sie die Anzahl der Artikel im Voraus nicht wissen, müssen Sie es zuerst zählen . Dann können Sie den Status nb tags read/total nb of tags
drucken, sagen Sie jeweils 100 Tags (counter % 100 == 0
).
Oder sogar einen anderen Thread überwachen den Fortschritt. In diesem Fall möchten Sie möglicherweise den Zugriff auf den Zähler synchronisieren, dies ist jedoch nicht erforderlich, da er nicht wirklich genau sein muss.
Meine 2 Cent
Ich fand das heraus, aber ich suchte nach einer Möglichkeit, es zu tun, ohne zuerst die Artikel zählen zu müssen. Ich dachte, dass es vielleicht eine Möglichkeit gäbe, die Position des Parsers in der Datei herauszufinden, weil ich die Dateigröße leicht erreichen kann. – Danijel
Sie können durch Überschreiben der Methode setDocumentLocator
von org.xml.sax.helpers.DefaultHandler/BaseHandler
eine Schätzung der aktuellen Zeile/Spalte in der Datei. Diese Methode wird mit einem Objekt aufgerufen, von dem Sie bei Bedarf eine Approximation der aktuellen Zeile/Spalte erhalten können.
Bearbeiten: Nach meinem Wissen gibt es keinen Standard Weg, um die absolute Position zu erhalten. Ich bin mir jedoch sicher, dass einige SAX-Implementierungen diese Art von Informationen anbieten.
Schließen, aber dann müsste ich die Anzahl der Zeilen in der Datei wissen, oder? – Danijel
In der Tat. Eine andere Idee könnte durch die rätselhafte EJP aufgezeigt worden sein. Sie können den Fortschritt schätzen, indem Sie den Fortschritt im Eingabestream verwenden. Dies ist jedoch nicht der Fortschritt in der Analyse, wegen möglicher Pufferung und Lookaheads. –
ich den Eingangsstrom Position verwenden würde. Machen Sie Ihre eigene triviale Stream-Klasse, die delegiert/erbt von der "echten" Klasse und verfolgt die gelesenen Bytes. Wie Sie sagen, ist es einfach, die gesamte Dateigröße zu erhalten. Ich mache mir keine Gedanken über Pufferung, Lookahead usw. - für große Dateien wie diese ist es Chickenfeed. Auf der anderen Seite würde ich die Position auf "99%" beschränken.
Dank EJPs Vorschlag von ProgressMonitorInputStream
habe ich am Ende FilterInputStream
erweitert, so dass ChangeListener
verwendet werden kann, um den aktuellen Leseort in Bytes zu überwachen.
Damit haben Sie feinere Kontrolle, zum Beispiel mehrere Fortschrittsbalken für das parallele Lesen von großen XML-Dateien anzuzeigen. Was genau ich getan habe.
So ist eine vereinfachte Version des überwachbar stream:
/**
* A class that monitors the read progress of an input stream.
*
* @author Hermia Yeung "Sheepy"
* @since 2012-04-05 18:42
*/
public class MonitoredInputStream extends FilterInputStream {
private volatile long mark = 0;
private volatile long lastTriggeredLocation = 0;
private volatile long location = 0;
private final int threshold;
private final List<ChangeListener> listeners = new ArrayList<>(4);
/**
* Creates a MonitoredInputStream over an underlying input stream.
* @param in Underlying input stream, should be non-null because of no public setter
* @param threshold Min. position change (in byte) to trigger change event.
*/
public MonitoredInputStream(InputStream in, int threshold) {
super(in);
this.threshold = threshold;
}
/**
* Creates a MonitoredInputStream over an underlying input stream.
* Default threshold is 16KB, small threshold may impact performance impact on larger streams.
* @param in Underlying input stream, should be non-null because of no public setter
*/
public MonitoredInputStream(InputStream in) {
super(in);
this.threshold = 1024*16;
}
public void addChangeListener(ChangeListener l) { if (!listeners.contains(l)) listeners.add(l); }
public void removeChangeListener(ChangeListener l) { listeners.remove(l); }
public long getProgress() { return location; }
protected void triggerChanged(final long location) {
if (threshold > 0 && Math.abs(location-lastTriggeredLocation) < threshold) return;
lastTriggeredLocation = location;
if (listeners.size() <= 0) return;
try {
final ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener l : listeners) l.stateChanged(evt);
} catch (ConcurrentModificationException e) {
triggerChanged(location); // List changed? Let's re-try.
}
}
@Override public int read() throws IOException {
final int i = super.read();
if (i != -1) triggerChanged(location++);
return i;
}
@Override public int read(byte[] b, int off, int len) throws IOException {
final int i = super.read(b, off, len);
if (i > 0) triggerChanged(location += i);
return i;
}
@Override public long skip(long n) throws IOException {
final long i = super.skip(n);
if (i > 0) triggerChanged(location += i);
return i;
}
@Override public void mark(int readlimit) {
super.mark(readlimit);
mark = location;
}
@Override public void reset() throws IOException {
super.reset();
if (location != mark) triggerChanged(location = mark);
}
}
Er weiß nicht, - oder Pflege - wie groß der zugrunde liegenden Stream ist, so müssen Sie es auf eine andere Weise zu bekommen, wie aus die Datei selbst
So, hier geht die vereinfachte Proben Nutzung:
try (
MonitoredInputStream mis = new MonitoredInputStream(new FileInputStream(file), 65536*4)
) {
// Setup max progress and listener to monitor read progress
progressBar.setMaxProgress((int) file.length()); // Swing thread or before display please
mis.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) {
SwingUtilities.invokeLater(new Runnable() { @Override public void run() {
progressBar.setProgress((int) mis.getProgress()); // Promise me you WILL use MVC instead of this anonymous class mess!
}});
}});
// Start parsing. Listener would call Swing event thread to do the update.
SAXParserFactory.newInstance().newSAXParser().parse(mis, this);
} catch (IOException | ParserConfigurationException | SAXException e) {
e.printStackTrace();
} finally {
progressBar.setVisible(false); // Again please call this in swing event thread
}
In meinem Fall die Fortschritte schön nach rechts, ohne anormalen Sprünge von links heben. Stellen Sie den Schwellenwert für ein optimales Verhältnis zwischen Leistung und Reaktionszeit ein. Zu klein und die Lesegeschwindigkeit kann sich bei kleinen Geräten mehr als verdoppeln, zu groß und der Fortschritt wäre nicht glatt.
Ich hoffe, es hilft. Fühlen Sie sich frei zu bearbeiten, wenn Sie Fehler oder Tippfehler gefunden haben, oder stimmen Sie ab, um mir einige Ermutigungen zu senden!: D
Ausgezeichnet! Genau das, was ich gesucht habe, werde ich anpassen, danke! :) – Matthieu
- 1. Sax Parser Codierung in Java
- 2. Java - SAX-Parser auf einem XHTML-Dokument
- 3. JAVA SAX-Parser Anrufe auf Zeichen aufteilen()
- 4. Load DTD in SAX-Parser in Java
- 5. CLojure Sax Parser Beispiele
- 6. SAX Parser Newline
- 7. SAX-Parser - Number
- 8. SAX XML-Parser oder DOM-Parser?
- 9. Leichter C++ SAX XML-Parser
- 10. Apache Digester Sax Parser Ausnahme
- 11. Erweiterte SAX-Parser in C#
- 12. SAX-Parser laden Sie die DTD-Datei
- 13. Java. Sax Parser. Wie man Parsing manuell bricht?
- 14. kann Daten mit SAX Parser nicht abrufen
- 15. SAX-Parser nicht nach Newline Lesen
- 16. Lese verschachtelte Tags mit SAX-Parser
- 17. SAX-Parser: Suchen HTML-Tags aus XML
- 18. machen SAX-Parser einen DOM-Baum
- 19. XML SAX-Parser - ignoriert ungebundene Präfix Ausnahme
- 20. SAX-Äquivalent in .Net
- 21. SAX-Parser - Umgang mit fehlerhaften Daten aus .XML-Datei
- 22. XML Parsing einiger Sonderzeichen mit SAX-Parser in Android
- 23. CDATA-Direktive fehlt in der SAX-Parser-Ausgabe
- 24. die Codierung für SAX-Parser in Python Einstellung
- 25. Android SAX-Parser nicht Volltext zwischen den Tags
- 26. Mit SAX Parser, erhalten Sie einen Attributs-Wert
- 27. Populate C++ POD Strukturen von SAX-Parser Ereignissen
- 28. SAX IncrementalParser in Jython
- 29. Wie man vollständige Daten zu analysieren & in Java-Sax Parser
- 30. Ruft ein Java-SAX-Parser die DTD tatsächlich aus dem Internet ab?
Ich denke, das wird nah genug sein. Vielen Dank! – Danijel
Kann eine Antwort einfacher sein ?! :) – Matthieu