繁体   English   中英

使用BOM表字符串处理utf-8时java的行为不一致

[英]java's inconsistent behavior when handling a utf-8 with BOM string

我打开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是零宽度的空间,因此原则上不可见。

但是,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代码点),则一切正常。

java的行为是相同的, FileInputStream不处理bom。

在Windows中,文件为file1 ,file1十六进制为EF BB BF 31 38

在linux中,您的文件为file2 ,file2的十六进制为31 38

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

我建议您使用记事本++将BOM文件转换为无BOM文件。

或者您可以使用BOMInputStream

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM