InputStreams

megalomaniac

Mitglied
Hallo zusammen,

folgendes Problem:
Ich habe ein Programm, dass XML-Dateien liest und an einen Parser weiterreicht:

Java:
FileInputStream inStream = new FileInputStream(inputPath + "/" + filename);
Object o = JDomProvider.parseXML(inStream);

Soweit keine Probleme.
Die Situation ist jetzt die, dass bestimmte Zeichen im XML umtransformiert werden müssen. Ich möchte das so realisieren, dass der InputStream auf einer tiefen Ebene "manipuliert" wird und möchte verhindern, im Programm mit Stringoperationen herumhampeln zu müssen.

Meine Vorstellung ist die Ableitung der Klasse InputStream, so dass die Zeichentransformierung direkt in der read-Methode der abgeleiteten Klasse stattfindet.

Java:
public class XmlFilterInputStream extends InputStream {
	InputStream in;
	
	public XmlFilterInputStream(InputStream in) {
		this.in = in;
	}

	public int read() throws IOException {
        // Hier sollen später die Transformationsregeln hin
		return in.read();
	}
}

Und die Änderung im aufrufenden Code:
Java:
FileInputStream inStream = new FileInputStream(inputPath + "/" + filename);
XmlFilterInputStream filterStream = new XmlFilterInputStream(inStream);
Object o = JDomProvider.parseXML(filterStream);

Bisher wird noch nichts transformiert, ich habe einfach nur eine Wrapperklasse über den FileInputStream gestülpt. Funktionieren tut es immernoch genauso wie vorher, mit der Ausnahme, dass die Verarbeitung deutlich länger dauert. Statt 1,8 Sekunden bei einem 7,5 MB XML-File, dauert die Verarbeitung jetzt stolze 9 Sekunden. Dabei habe ich die Transformationsregeln noch gar nicht implementiert.

Kann mir das bitte jemand erklären? Was mache ich falsch?
 
S

SlaterB

Gast
InputStream, von der du erbst, ist nunmal eine besch..ränkte Klasse,
dort gibt es eine Implementierung

Java:
public int read(byte b[], int off, int len) throws IOException {
[..]
	    for (; i < len ; i++) {
		c = read();
		if (c == -1) {
		    break;
		}
		b[off + i] = (byte)c;
	    }
[..]
    }
jedes Byte wird also einzeln eingelesen, bzw. führt zumindest zu extra einzelner Java-interner Übertragung,
was deiner Transformation direkt in der read()-Methode entgegen kommt, denn so kommt sie überhaupt dran, aber recht langsam ist,
aus einem Byte kannst du eh nichts sinnvolles machen, also besser anders vorgehen,

und zwar die Methode read(byte b[], int off, int len) oder eine andere überschreiben,
und dann read(byte b[], int off, int len) vom übergebenen Stream aufrufen, schon werden tausende Bytes auf einmal geladen,
falls der übergebene Stream das unterstützt, wovon mal auszugehen ist,
und falls der Aufrufer diese Methode nutzt, wovon auch auszugehen ist,

wenn du nix weiter machst, sollten es wieder 1.8 sec sein, ansonsten mit dem byte[] was anstellen,
was schon realistischer ist, auch wenn ich mir kaum vorstellen kann, dass du da zu etwas gutem kommst,
bytes sind keine chars..

JDomProvider akzeptiert vielleicht auch einen Reader,
überschreibe lieber einen Reader auf einen Stream, dann hast du wenigestens Zeichen, Wörter, Zeilen statt Bytes in ungewissen Encoding
 
Zuletzt bearbeitet von einem Moderator:

megalomaniac

Mitglied
Danke schonmal für die Antwort.

Was ich an dieser Stelle nicht verstehe:
Diese (vermeindlich inperformante) read(byte[], int, int)-Methode muss doch auch vorher schon ganz normal vom Parser aufgerufen worden sein. Daran ändert sich mit meiner abgeleiteten Klasse doch überhaupt nichts. Wo soll denn plötzlich dieser immense Performanzverlust herkommen...
 

Ark

Top Contributor
Was ich an dieser Stelle nicht verstehe:
Diese (vermeindlich inperformante) read(byte[], int, int)-Methode muss doch auch vorher schon ganz normal vom Parser aufgerufen worden sein. Daran ändert sich mit meiner abgeleiteten Klasse doch überhaupt nichts. Wo soll denn plötzlich dieser immense Performanzverlust herkommen...
Wenn du die Methode in einer abgeleiteten Klasse überschreibst, wird die neue Implementierung verwendet. Überhaupt wird immer die tatsächliche/aktuelle/zum tatsächlichen Typ gehörende verwendet (denke ich jedenfalls ^^).

Ark
 
S

SlaterB

Gast
> Daran ändert sich mit meiner abgeleiteten Klasse doch überhaupt nichts. Wo soll denn plötzlich dieser immense Performanzverlust herkommen...

ja es ist nicht leicht (umso schlauer bin ich :D ),
vorher wurde read(Array) des FileInputStream verwendet, welche schnell war,

nun wird read(Array) der Klasse InputStream verwendet, die diesen Aufruf nicht zu read(Array) des FileInputStream weiterleitet,
sondern daraus tausende einzelne Aufrufe macht,

hier noch eine schöne Simulation ;)
Java:
public class Test {
    public static void main(String[] args)  {
        FileStream f = new FileStream();
        go(f);
        FilterStream ff = new FilterStream(f);
        go(ff);
    }

    public static void go(Stream s)  {
        long time = System.currentTimeMillis();
        s.readMany();
        System.out.println("ready go, time: " + (System.currentTimeMillis() - time) + ", " + s);
    }
}
interface Stream {
    public void readMany();
    public void readOne();
}
class FileStream   implements Stream {
    public void readOne()  {
        try    {  Thread.sleep(10);  }
        catch (InterruptedException e)  {  }
    }

    public void readMany() {
        try  {  Thread.sleep(100);  }
        catch (InterruptedException e)  {   }
    }
}

class FilterStream implements Stream {
    Stream s;

    public FilterStream(Stream in)  {
        this.s = in;
    }

    public void readOne()  {
        s.readOne();
    }

    public void readMany() {
        for (int i = 0; i < 100; i++)   {
            readOne();
        }
    }
}
 
Zuletzt bearbeitet von einem Moderator:

Ähnliche Java Themen

Neue Themen


Oben