java在处理带有BOM字符串的utf-8时行为不一致

标签 java utf-8

我打开 Windows 记事本,输入 18,并将文件保存为 utf-8 编码。我知道我的文件将具有 BOM header ,并且我的文件是 utf-8 编码文件(带有 BOM header )。

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

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

在 Windows 中我得到:

?18

但是在 Linux 中我得到了:

18

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

最佳答案

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

但是 Window 没有 UTF-8 编码,而是使用多种单字节编码之一。从 String 到输出的转换会将字符集中缺少的 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 代码点),那么一切都会正常。

关于java在处理带有BOM字符串的utf-8时行为不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55273476/

相关文章:

c# - 将 c# 数据类型转换为等效的 java 数据类型

java - 如何围绕 <Array> 矩形绘制矩形

java - 捕获 Control + Space 键盘事件

java - 使用 Java-JDBC 从 Oracle 数据库读取数据时的字符编码

使用 FileWriter 进行 Java UTF-8 编码

PHP:在不知道原始字符集的情况下将任何字符串转换为 UTF-8,或者至少尝试一下

java - 如何按优先级迭代?

java - 为导入的 Spring XML 资源设置前缀

PHP:将 Unicode 字符串转换为 ANSI 字符串

php - UTF-8贯穿始终