[英]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.