2015-04-30 13 views
5

Als Teil meines Java-Kurses schrieb ich einen "Zip" -Schreiber und -Leser - so funktioniert der Huffman-Algorithmus.Leser erweitern, wie kann ich mein "Lesen" zurückgeben?

Meine Klasse erweitert Reader, und haben ein Objekt Reader r. In meinem Haupt-Methode, ich habe diese Zeilen:

input = new BufferedReader(new HuffmanReader(new FileReader("output.hff"))); 
String str = input.readLine(); 

Es sollte die dekomprimierte Zeichenkette kehre ich in die Datei geschrieben, nachdem es dekomprimiert, natürlich. Aber es gibt die erste Zeile der Datei zurück!

Meine Lesefunktion:

public int read(char[] cbuf, int off, int len) throws IOException { 
    //... 
    r.read(buffer,0,8192) 
    //does the decompress process 
    String fnlStr = ... //The final result 
    cbuf = fnlStr.toCharArray(); 
    //close streams 
    return cbuf.length; 
} 

Meine Debug-Fenster zeigt dies:

HuffmanReader.read(char[], int, int) line: 23 
BufferedReader.fill() line: not available 
BufferedReader.readLine(boolean) line: not available  
BufferedReader.readLine() line: not available 
Run.main(String[]) line: 23 

Es ruft meine Lesefunktion zweimal. Wie kann ich verhindern, dass der bufferReader die Lesefunktion erneut aufruft?

+0

1. Halten Sie 'off' und' len' in Ihrer 'read()' Funktion? 2. Benötigen Sie diesen BufferedReader (können Sie nicht ohne ihn testen)? – xerx593

+1

Die einzige Stelle, an der Sie von 'input' lesen, ist in' input.readLine() ', die natürlich nur eine Zeile liest. Ich bin ein wenig überrascht, dass deine 'read'-Funktion überhaupt funktioniert, weil du nicht wirklich in den übergebenen Puffer schreibst, sondern einfach' cbuf' einen neuen Puffer zuweist. – dddsnn

+0

Sie verwenden auch die von 'r.read() zurückgegebene Anzahl nicht.' Dieser Code kann möglicherweise nicht funktionieren. – EJP

Antwort

2

Sie geben die Daten, die Sie von der Methode gelesen haben, nicht wie gewöhnlich zurück. Wenn read aufgerufen wird, gibt der Aufrufer stattdessen das Array cbuf, das ist im Wesentlichen die Adresse eines Chunks des Speichers, und fordert Sie auf, lenchar s in es schreiben.

Wenn Sie cbuf = fnlStr.toCharArray() tun, ersetzen Sie gerade Ihre lokale Kopie dieser Adresse durch eine andere Adresse, aber Sie ändern nicht wirklich den Speicher, in den Sie schreiben sollten. Sie müssen entweder über das Array, das Sie in einer for-Schleife angegeben haben, iterieren und darauf schreiben, oder System.arraycopy verwenden, wenn Sie einen anderen Puffer erstellt haben, der das Ergebnis enthält.

Z. B. wird die folgende read Methode immer "Test\n" lesen:

public int read(char[] cbuf, int off, int len) throws IOException { 
    char[] result = "Test\n".toCharArray(); 
    int numRead = Math.min(len, result.length); 
    System.arraycopy(result, 0, cbuf, off, numRead); 
    return numRead; 
} 

die "Test\n" wörtlichen mit dekomprimiert String austauschen sollten Sie begonnen erhalten. Natürlich müssen Sie noch verwalten, wie viel von Ihrer Quelle Sie bereits verbraucht haben.


Und was BufferedReaderread zweimal anrufen: Sie sollten es nicht egal, wie oft genannt wird. Holen Sie einfach die Daten von Ihrer zugrunde liegenden Quelle, schreiben Sie sie an cbuf und geben Sie die Nummer char s zurück, die Sie geschrieben haben. Wenn nichts mehr zu lesen ist, geben Sie -1 zurück, um das Ende des Streams zu signalisieren (in diesem Fall hört BufferedReader auf, read aufzurufen).


Als beiseite, Reader gemeint Charakter Ströme zu lesen, während InputStream is for binary data (es ist im Grunde die gleiche Sache ist, nur mit byte[] statt char[] und ohne charset zu verwenden). Da komprimierte Dateien binär sind, möchten Sie möglicherweise Ihre FileReader zu FileInputStream wechseln.

Ich könnte mir komische Fehler vorstellen, wenn aus irgendeinem Grund der Zeichensatz, mit dem Sie kodieren, nicht mit dem übereinstimmt, mit dem Sie dekodieren. Oder weniger dramatisch, Sie könnten mehr Platz als Sie denken, wenn eine 16-Bit-Code-Einheit in UTF-16 3 8-Bit-Code-Einheiten in UTF-8 benötigt.

+0

Vielen Dank! Das war mein Problem. Es läuft gut! Ich kenne das Problem mit dem Reader, es ist eine Grenze, die wir für diese Übung hatten. Vielen Dank. –

1

Sie lesen nur die erste Zeile. Ändern Sie den ersten Teil zu so etwas wie:

input = new BufferedReader(new HuffmanReader(new FileReader("output.hff"))); 
Arraylist<String> list = new ArrayList<String>(); 
String line; 

while ((line = reader.readLine()) != null) { 
    list.add(line); 
} 

Und auch, zu beheben, dass Ihre Methode zweimal aufgerufen wird, eine boolean machen und setzen Sie ihn auf true, nachdem Sie Ihre Sachen in der Methode getan haben. Überprüfen Sie dann am Anfang dieser Methode, ob dieser Wahrheitswert wahr ist. Wenn dies der Fall ist, kehren Sie von der Methode zurück, damit sie nicht danach erneut ausgeführt wird.

+0

Oder rufe einfach mal die Methode an ;-) – EJP

+0

@ ImBatman64 Hi, ich habe früher die Boolean-Sache probiert und es hat nicht funktioniert, weil ich nicht weiß, wie ich mein Ergebnis in den Puffer schreiben soll. Wenn es das nächste Mal kommt, kehrt es zu String string mit einigen Leerzeichen zurück. Ich kann den Hauptteil nicht ändern - es ist Teil der Übung. Der BufferedReader versucht erneut zu lesen, obwohl er nur eine Zeile lesen sollte. –

+0

@RoeiJacobovich Wo nennen Sie die Methode genau? – ImBatman64

Verwandte Themen