Commit e7efb154 by Patryk Czarnik

Przykład SAX

parent 75554dbe
package p20_xml;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
public class Waluty6_Sax {
public static void main(String[] args) {
File plik = new File("pliki/waluty2023.xml");
String szukanaWaluta = "EUR";
try {
System.out.println("Startujemy");
long t1 = System.nanoTime();
WalutyHandler handler = new WalutyHandler(szukanaWaluta);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
SAXParser parser = factory.newSAXParser();
parser.parse(plik, handler);
long t3 = System.nanoTime();
Runtime runtime = Runtime.getRuntime();
System.out.printf("Czas łączny : %.6f s%n", (t3-t1) * 1e-9);
System.out.printf("Zajęta pamięć : %,d B%n", runtime.totalMemory() - runtime.freeMemory());
System.gc();
Thread.sleep(1000);
System.out.printf("Zajęta pamięć po gc: %,d B%n", runtime.totalMemory() - runtime.freeMemory());
handler.printResults();
} catch (Exception e) {
e.printStackTrace();
}
}
private static enum Stan {
DOMYSLNY,
/** znajduję się wewnątrz elementu Code i odczytuję tekstowy kod waluty */
CODE,
/** znajduję się wewnątrz Rate i wiem, że mam do czynienia z szukaną walutą */
NASZA_WALUTA,
/** znajduję się wewnątrz elementu Mid szukanej waluty */
MID,
}
private static class WalutyHandler extends DefaultHandler {
private final String szukanaWaluta;
private Stan stan = Stan.DOMYSLNY;
private StringBuilder buf = null;
private int count = 0;
private double sum = 0, min = Double.MAX_VALUE, max = Double.MIN_VALUE;
public WalutyHandler(String szukanaWaluta) {
this.szukanaWaluta = szukanaWaluta;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if("Code".equals(localName)) {
// musimy sprawdzić, czy nazwa waluty się zgadza
// ale w SAX nie ma możliwości odczytania zawartości tekstowej, gdy znajdujemy się w początku elementu,
// trzeba to zrobić w metodzie characters
stan = Stan.CODE;
buf = new StringBuilder();
} else if("Mid".equals(localName) && stan == Stan.NASZA_WALUTA) {
stan = Stan.MID;
buf = new StringBuilder();
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if(stan == Stan.CODE) {
if(szukanaWaluta.contentEquals(buf)) {
stan = Stan.NASZA_WALUTA;
} else {
stan = Stan.DOMYSLNY;
}
buf = null;
} else if(stan == Stan.MID) {
double mid = Double.parseDouble(buf.toString());
count++;
sum += mid;
if(mid < min) min = mid;
if(mid > max) max = mid;
buf = null;
stan = Stan.DOMYSLNY;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
/* Ponieważ w ogólności parsery SAX mają prawo podzielić węzeł tekstowy na części
i wywołać wiele razy characters dla jednego węzeła tekstowego,
to musimy fragmenty tekstu "skleić" za pomocą StringBuilder.
Dopiero w metodzie endElement wiemy, że tekst się skończył i tam z niego skorzystamy.
*/
if(stan == Stan.CODE || stan == Stan.MID) {
buf.append(ch, start, length);
}
}
public int getCount() {
return count;
}
public double getSum() {
return sum;
}
public double getMin() {
return min;
}
public double getMax() {
return max;
}
public double getAverage() {
return sum / count;
}
public String getSzukanaWaluta() {
return szukanaWaluta;
}
public void printResults() {
System.out.println("Count: " + count);
if(count > 0) {
System.out.println("Avg: " + getAverage());
System.out.println("Min: " + min);
System.out.println("Max: " + max);
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment