读UTF-8 - BOM标记

oni*_*unn 62 java encoding file

我正在通过FileReader读取文件 - 该文件是UTF-8解码的(带有BOM)现在我的问题是:我读取文件并输出一个字符串,但遗憾的是BOM标记也输出了.为什么会这样?

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");
}
Run Code Online (Sandbox Code Playgroud)

第一行后的输出

?<style>
Run Code Online (Sandbox Code Playgroud)

Rea*_*wTo 71

在Java中,您必须手动使用UTF8 BOM(如果存在).Java bug数据库中记录了此行为,此处此处.暂时没有解决方法,因为它会破坏JavaDoc或XML解析器等现有工具.在Apache的IO共享提供了一个BOMInputStream处理这种情况.

看看这个解决方案:处理带有BOM的UTF8文件

  • +1用于指出Apache IO Commons BOMInputStream. (3认同)

fin*_*nnw 33

最简单的修复可能只是\uFEFF从字符串中删除结果,因为它几乎不可能出于任何其他原因.

tmp = tmp.replace("\uFEFF", "");
Run Code Online (Sandbox Code Playgroud)

另请参阅此番石榴错误报告

  • 关于"极不可能"的坏处是它很少出现,所以定位错误是非常困难的...... :)因此,如果你相信你的软件会成功并且长寿,那么在使用这段代码时要非常小心,因为迟早会出现任何现有情况. (4认同)
  • `FEFF`是一个UTF-16 BOM.UTF-8 BOM是`EFBBBF`. (4认同)
  • @StevePitchers但我们必须在*解码之后匹配它,当它是`String`(它总是表示为UTF-16)的一部分时 (4认同)

pee*_*nut 26

使用Apache Commons库.

类: org.apache.commons.io.input.BOMInputStream

用法示例:

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();
}
Run Code Online (Sandbox Code Playgroud)


sna*_*tor 7

以下是我使用Apache BOMInputStream的方法,它使用了try-with-resources块."false"参数告诉对象忽略以下BOM(出于安全原因,我们使用"无BOM"文本文件,哈哈):

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)

}
Run Code Online (Sandbox Code Playgroud)

  • 永远不知道如何在这个网站上发布东西 - 总是以 AFU 告终。 (2认同)

Adr*_*ith 6

考虑一下来自 Google 的UnicodeReader,它可以为您完成所有这些工作。

Charset utf8 = Charset.forName("UTF-8"); // default if no BOM present
try (Reader r = new UnicodeReader(new FileInputStream(file), utf8)) {
    ....
}
Run Code Online (Sandbox Code Playgroud)

Maven 依赖:

<dependency>
    <groupId>com.google.gdata</groupId>
    <artifactId>core</artifactId>
    <version>1.47.1</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)


paw*_*man 5

使用Apache Commons IO

例如,让我们看一下下面的代码(用于读取包含拉丁字符和西里尔字符的文本文件):

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();
Run Code Online (Sandbox Code Playgroud)

因此,我们有一个名为“ari”的 ArrayList,其中包含文件“1.txt”中除 BOM 之外的所有字符。