【问题标题】:java's inconsistent behavior when handling a utf-8 with BOM stringjava在处理带有BOM字符串的utf-8时的不一致行为
【发布时间】:2019-03-21 03:45:42
【问题描述】:

我打开我的 Windows 记事本,输入 18,然后将文件保存为 utf-8 编码。我知道我的文件会有一个 BOM 标头,而我的文件是一个 utf-8 编码的文件(带有一个 BOM 标头)。

问题是,当通过以下代码打印该字符串时:

//str is that string read from the file using StandardCharsets.UTF_8 encoding
System.out.println(str);

在 Windows 中我得到了:

?18

但在 linux 中我得到了:

18

那么为什么java的行为不同呢?怎么理解?

【问题讨论】:

  • 无论您以何种方式将文本文件内容转换为字符串,都是错误的。字符串用于文本。 BOM 是元数据。请出示代码。

标签: java utf-8


【解决方案1】:

BOM 是一个零宽度空间,因此原则上是不可见的。

但是 Window 没有 UTF-8 编码,而是使用许多单字节编码中的一种。从字符串到输出的转换会将字符集中缺少的 BOM 变成问号。

仍然记事本会识别 BOM 并显示 UTF-8 文本。

现在的Linux一般使用UTF-8,所以没有问题,在控制台也是。


进一步说明

在 Windows 上,System.out 使用控制台,例如,该控制台用作字符集/编码,例如 Cp-850,大约 256 个字符的单字节字符集。很可能缺少ĉ 或BOM 字符。如果 java 字符串包含这些字符,则它们不能被编码为 256 个可用字符之一。因此它们将被转换为?

使用CharsetEncoder

String s = ...
CharsetEncoder encoder = Charset.defaultCharset().newEncoder();
if (!encoder.canEncode(s)) {
    System.out.println("A problem");
}

Windows 通常也以单字节编码运行,例如 Cp-1252。又是 256 个字符。但是编辑器可能会处理多种编码,如果字体可以代表字符(Unicode 代码点),那么一切正常。

【讨论】:

  • 如果Windows没有UTF-8编码,我们如何在记事本中将文件保存到utf-8
  • @ZhaoGang:记事本将处理编码。注意:我假设微软正在推动大量的 BOM(也在 UTF-8 上),以表明哪种编码。我预计它们会“很快”转换为 UTF-8(作为用户界面),就像其他操作系统已经做到的那样。
  • 顺便说一句:最初 BOM 是一个零宽度空间,但现在它应该只用作第一个代码点,如 BOM。对于真正的ZWSP,最好使用新的U+200B
  • 仍然对Window has no UTF-8 encoding but uses one of the many single byte encodings. The conversion from String to the output will turn the BOM, missing in the charset, into a question mark.Notepad will recognize the BOM and display UTF-8 text. 感到困惑,你能解释一下吗?谢谢。
  • 如果记事本可以识别BOM并显示UTF-8文本,为什么Windows不能?
【解决方案2】:

java的行为也是一样,FileInputStream不处理bom。

在 Windows 中,你的文件是 file1,file1 hex 是 EF BB BF 31 38

在linux中,你的文件是file2,file2的十六进制是31 38

当你阅读它们时,你会得到不同的字符串。

我建议您使用 notepad++ 将您的 bom 文件转换为无 bom 文件。

或者你可以使用BOMInputStream

【讨论】:

  • 我没有改文件,只是从windows复制到linux。
  • “当你阅读它们时,你应该得到不同的字符串”,不,你可以但不应该。 String 不应包含 BOM,这是您引用的 BOMInputStream 库的点。
  • @ZhaoGang 你可以使用wc -c yourfilename.txtfile yourfilename.txt 来检测bom。也许您的传输工具将bom添加到您的文件中。
猜你喜欢
  • 2012-02-12
  • 2011-11-08
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 2019-03-08
  • 2016-06-09
  • 2023-03-27
  • 2013-07-26
相关资源
最近更新 更多