2016-03-19 13 views
2

Ich versuche, eine benutzerdefinierte FilterReader-Klasse zu implementieren. Die Klasse soll transformieren, was sie liest (egal wie). Das Problem, das ich habe ist, dass die Zeichenfolge nach der Transformation länger ist als die ursprüngliche in den Zeichenpuffer gelesen, so bekomme ich eine ArrayIndexOutOfBoundsException, wenn ich versuche, die neue Zeichenfolge in den Puffer zu stopfen.Wie implementiert man einen benutzerdefinierten FilterReader?

Hier ist die read() Methode meiner benutzerdefinierten Filterreader Klasse:

@Override 
public int read(char[] cbuf, int off, int len) throws IOException { 
    int result = in.read(cbuf, off, len); 

    if(result != -1){ 
     String str = new String(cbuf, off, len); 
     str = someStringTranformationMethod(str); 

     //cbuf = new char[str.length()]; 

     str.getChars(0, str.length(), cbuf, 0); 

     result = str.length(); 
    } 

    return result; 
} 

Ich dachte, ich es für cbuf durch Neuzuweisung einen neuen char buffer lösen könnte, das, was ich in der Kommentarzeile versucht ist. Dies scheint jedoch überhaupt nicht zu funktionieren, weil dann meine Ausgabe vom Leser die ursprüngliche (nicht transformierte) Zeichenkette ist.

Ich habe das Gefühl, dass ich hier komplett rückwärts laufe, aber es ist nicht einfach, online gute Beispiele zu finden. Alle benutzerdefinierten FilterReader, die ich gefunden habe, haben gerade einige grundlegende Ober-/Unterkürzungen der Zeichen gemacht, wobei die Länge der neuen Zeichenkette dieselbe wie die ursprüngliche Zeichenkette ist.

Also wie würde ich dies mit einer String-Transformation-Funktion, die zu einer längeren Zeichenfolge als die ursprüngliche führt implementieren?

+0

Wenn es eine Obergrenze für den Quotienten von str.lengths nach und vor der Transformation gibt, kann der Lesevorgang die Länge entsprechend reduzieren, so dass die transformierten Zeichen immer noch in den Puffer passen. – laune

+0

Als eine (komplexere) Alternative müsste someStringTransformationMethod über seine maximale Ausgabelänge wissen und die überschüssigen Zeichen zwischenspeichern, um mit dem nächsten Aufruf weitergeleitet zu werden. In diesem Fall sollte der Transformator eine Methode bereitstellen, um den Anrufer über die Länge anstehender Daten zu informieren, so dass ein Anruf ohne zusätzliches Lesen angezeigt wird. (Dies verhindert eine unbegrenzte Ansammlung zwischengespeicherter Daten.) – laune

+0

Kann man anhand des Wertes von 'len' die Länge der resultierenden Zeichenkette ermitteln? Wenn ja, können Sie nicht die Anzahl der zu lesenden Zeichen aus dem Quelldatenstrom berechnen, die Ihnen eine len Zeichenausgabe liefern? – WeaponsGrade

Antwort

2

Sie benötigen Ihre Implementierung Stateful zu machen und den Überblick über die „übrig gebliebenen“ Zeichen halten:

private String str = ""; 
private int pos = 0; 

public int read(char[] cbuf, int off, int len) throws IOException { 
    if (pos == str.length()) { 
    // No leftovers from a previous call available, need to actully read more 
    int result = in.read(cbuf, off, len); 
    if(result <= 0){ 
     return -1; 
    } 
    str = new String(cbuf, off, result); 
    str = someStringTranformationMethod(str); 
    pos = 0; 
    } 

    // Return as much as we have available, but not more than len 
    int available = Math.min(str.length() - pos, len);  
    str.getChars(pos, pos + available, cbuf, off); 
    pos += available; 
    return available; 
} 

Beachten Sie, dass nur gelesen() nur lesen muss (at least) ein Zeichen, wenn das Ende der Stream wurde nicht erreicht. Diese Implementierung nutzt dies aus.

+0

Funktioniert wie ein Charme! – BadCash

Verwandte Themen