2010-09-27 7 views
16

Die fragliche Datei ist nicht unter meiner Kontrolle. Die meisten Bytefolgen sind gültig UTF-8, es ist nicht ISO-8859-1 (oder eine andere Kodierung). Ich möchte mein Bestes tun, um so viele Informationen wie möglich zu extrahieren.Wie erkennen Sie illegale UTF-8-Byte-Sequenzen, um sie in Java-Inputstream zu ersetzen?

Die Datei enthält einige ungültige Bytefolgen, diese sollten durch das Ersatzzeichen ersetzt werden.

Es ist keine einfache Aufgabe, es erfordert einige Kenntnisse über die UTF-8-Zustandsmaschine.

Oracle hat einen Wrapper, der das tut, was ich brauche:
UTF8ValidationFilter javadoc

Gibt es so etwas wie die zur Verfügung (im Handel oder als freie Software)?

Dank
-Stephan

Lösung:

final BufferedInputStream in = new BufferedInputStream(istream); 
final CharsetDecoder charsetDecoder = StandardCharsets.UTF_8.newDecoder(); 
charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE); 
charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPLACE); 
final Reader inputReader = new InputStreamReader(in, charsetDecoder); 
+10

Ich hasse das. Content-Produzenten sollten gültige Inhalte produzieren und die Konsumenten nicht dazu auffordern, zu raten und zu korrigieren. Das hat in unserer Branche so viel Ärger verursacht. – irreputable

Antwort

12

java.nio.charset.CharsetDecoder tut, was Sie brauchen. Diese Klasse bietet eine Zeichensatzdekodierung mit benutzerdefinierbaren Aktionen für verschiedene Arten von Fehlern (siehe onMalformedInput() und onUnmappableCharacter()).

CharsetDecoder schreibt an einem OutputStream, das Sie können Rohr in einen InputStreamjava.io.PipedOutputStream verwenden, effektiv eine gefilterte InputStream zu schaffen.

+0

Das war schnell hilfreich, danke. – user85155

+0

@Henning - was, wenn ich wissen möchte, auf welcher Linie dort schlechte Zeichen? – Dejell

+1

@Dejel können Sie die Eingabe in Zeilen aufteilen und versuchen, Fehler Zeile pro Zeile zu erkennen. –

0

Ein Weg wäre, die ersten paar Bytes zu lesen, um die Byte Order Mark (falls vorhanden) zu prüfen. Weitere Informationen zur Stückliste: http://en.wikipedia.org/wiki/Byte_order_mark In der angegebenen URL finden Sie eine Tabelle der Stücklistenbytes. Ein Problem ist jedoch, dass UTF-8 keine Stückliste in seinem Header benötigt. Es gibt eine andere Möglichkeit, das Problem durch Mustererkennung zu lösen (lesen Sie einige Bytes - jeweils 8 Bit). Wie auch immer, das ist die komplizierte Lösung.

+0

Das Problem war keine Stückliste, es wurde bereits entfernt. Es gibt einen BOMStripperInputStream, der hier verfügbar ist: http://code.google.com/p/train-graph/source/browse/trunk/src/org/paradise/etrc/data/BOMstripperInputStream.java?r=31 – user85155

0

Das gewünschte Verhalten ist bereits der Standard für InputStreamReader. Sie müssen es also nicht selbst festlegen. Das genügt:

final BufferedInputStream in = new BufferedInputStream(istream); 
final Reader inputReader = new InputStreamReader(in, StandardCharsets.UTF_8); 
Verwandte Themen