Ich lese eine Datei über einen FileReader - die Datei ist UTF-8-decodiert (mit Stückliste). Mein Problem ist nun: Ich lese die Datei und gebe eine Zeichenfolge aus, aber leider wird auch die Stücklistenmarkierung ausgegeben. Warum tritt das auf?
fr = new FileReader(file);
br = new BufferedReader(fr);
String tmp = null;
while ((tmp = br.readLine()) != null) {
String text;
text = new String(tmp.getBytes(), "UTF-8");
content += text + System.getProperty("line.separator");
}
Ausgabe nach der ersten Zeile
?<style>
Antworten:
In Java müssen Sie die UTF8-Stückliste manuell verwenden, falls vorhanden. Dieses Verhalten ist hier und hier in der Java-Fehlerdatenbank dokumentiert . Derzeit wird es keine Lösung geben, da vorhandene Tools wie JavaDoc oder XML-Parser beschädigt werden. Die Apache IO Commons bietet eine
BOMInputStream
, diese Situation zu bewältigen.Schauen Sie sich diese Lösung an: Behandeln Sie die UTF8-Datei mit der Stückliste
quelle
Die einfachste Lösung besteht wahrscheinlich darin, das Ergebnis
\uFEFF
aus der Zeichenfolge zu entfernen , da es aus einem anderen Grund äußerst unwahrscheinlich ist, dass es angezeigt wird.tmp = tmp.replace("\uFEFF", "");
Siehe auch diesen Guava-Fehlerbericht
quelle
FEFF
ist eine UTF-16-Stückliste. Die UTF-8-Stückliste istEFBBBF
.String
(der immer als UTF-16 dargestellt wird) ist\uFFFE
(UTF-16, Little-Endian)?Verwenden Sie die Apache Commons-Bibliothek .
Klasse:
org.apache.commons.io.input.BOMInputStream
Anwendungsbeispiel:
String defaultEncoding = "UTF-8"; InputStream inputStream = new FileInputStream(someFileWithPossibleUtf8Bom); try { BOMInputStream bOMInputStream = new BOMInputStream(inputStream); ByteOrderMark bom = bOMInputStream.getBOM(); String charsetName = bom == null ? defaultEncoding : bom.getCharsetName(); InputStreamReader reader = new InputStreamReader(new BufferedInputStream(bOMInputStream), charsetName); //use reader } finally { inputStream.close(); }
quelle
Hier ist, wie ich den Apache BOMInputStream verwende, er verwendet einen Try-with-Resources-Block. Das Argument "false" weist das Objekt an, die folgenden Stücklisten zu ignorieren (wir verwenden aus Sicherheitsgründen Textdateien ohne Stückliste, haha):
try( BufferedReader br = new BufferedReader( new InputStreamReader( new BOMInputStream( new FileInputStream( file), false, ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32LE ) ) ) ) { // use br here } catch( Exception e) }
quelle
Betrachten Sie UnicodeReader von Google, der all dies für Sie erledigt.
Charset utf8 = Charset.forName("UTF-8"); // default if no BOM present try (Reader r = new UnicodeReader(new FileInputStream(file), utf8)) { .... }
Maven-Abhängigkeit:
<dependency> <groupId>com.google.gdata</groupId> <artifactId>core</artifactId> <version>1.47.1</version> </dependency>
quelle
Verwenden Sie Apache Commons IO .
Schauen wir uns zum Beispiel meinen Code an (der zum Lesen einer Textdatei mit lateinischen und kyrillischen Zeichen verwendet wird):
String defaultEncoding = "UTF-16"; InputStream inputStream = new FileInputStream(new File("/temp/1.txt")); BOMInputStream bomInputStream = new BOMInputStream(inputStream); ByteOrderMark bom = bomInputStream.getBOM(); String charsetName = bom == null ? defaultEncoding : bom.getCharsetName(); InputStreamReader reader = new InputStreamReader(new BufferedInputStream(bomInputStream), charsetName); int data = reader.read(); while (data != -1) { char theChar = (char) data; data = reader.read(); ari.add(Character.toString(theChar)); } reader.close();
Als Ergebnis haben wir eine ArrayList mit dem Namen "ari" mit allen Zeichen aus der Datei "1.txt" mit Ausnahme der Stückliste.
quelle
Es wird hier erwähnt dass dies normalerweise ein Problem mit Dateien unter Windows ist.
Eine mögliche Lösung wäre, die Datei zuerst über ein Tool wie dos2unix auszuführen.
quelle
dos2unix
(was Teil von Cygwin ist) hat Optionen zum Hinzufügen (--add-bom
) und Entfernen (--remove-bom
) von bom.Wenn jemand es mit dem Standard machen möchte, wäre dies ein Weg:
public static String cutBOM(String value) { // UTF-8 BOM is EF BB BF, see https://en.wikipedia.org/wiki/Byte_order_mark String bom = String.format("%x", new BigInteger(1, value.substring(0,3).getBytes())); if (bom.equals("efbbbf")) // UTF-8 return value.substring(3, value.length()); else if (bom.substring(0, 2).equals("feff") || bom.substring(0, 2).equals("ffe")) // UTF-16BE or UTF16-LE return value.substring(2, value.length()); else return value; }
quelle
Der einfachste Weg, die Stückliste zu umgehen
BufferedReader br = new BufferedReader(new InputStreamReader(fis)); while ((currentLine = br.readLine()) != null) { //case of, remove the BOM of UTF-8 BOM currentLine = currentLine.replace("","");
quelle