即使使用UTF-8,为什么在Windows与Linux中显示不同?

为什么以下在Linux与Windows中显示不同?

System.out.println(new String("¿".getBytes("UTF-8"), "UTF-8")); 

在Windows中:

¿

在Linux中:

一个

System.out.println()以系统默认编码输出文本,但控制台根据自己的编码(或“代码页”)设置解释该输出。 在您的Windows机器上,两个编码似乎匹配,但在Linux机器上,输出显然是UTF-8,而控制台将其解码为像ISO-8859-1这样的单字节编码。 或者,正如Jon建议的那样,源文件被保存为UTF-8,而javac正在将其作为其他东西读取,这是一个可以通过使用Unicode转义来避免的问题。

当您需要输出除ASCII文本以外的任何内容时,最好的办法是使用适当的编码将其写入文件,然后使用文本编辑器读取文件 – 控制台太有限且太依赖于系统。 顺便说一句,这段代码:

 new String("¿".getBytes("UTF-8"), "UTF-8") 

……对输出没有影响。 所有这一切都是将字符串的内容编码为字节数组并再次解码,再现原始字符串 – 一个昂贵的无操作。 如果要以特定编码输出文本,则需要使用OutputStreamWriter,如下所示:

 FileOutputStream fos = new FileOutputStream("out.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); 

不确定问题究竟在哪里,但值得注意的是

¿(0xc2,0xbf)

是使用UTF-8编码的结果

为0xBF,

这是¿的Unicode代码点

因此,在linux的情况下,输出不会显示为utf-8,而是显示为单字节字符串

检查你的linux终端有什么编码。

对于ubuntu中的gnome-terminal – 转到“终端”菜单并选择“设置字符编码”。

对于putty,配置 – >窗口 – >翻译 – > UTF-8(如果这不起作用,请参阅此post )。

运行此代码以帮助确定它是编译器还是控制台问题:

 public static void main(String[] args) throws Exception { String s = "¿"; printHex(Charset.defaultCharset(), s); Charset utf8 = Charset.forName("UTF-8"); printHex(utf8, s); } public static void printHex(Charset encoding, String s) throws UnsupportedEncodingException { System.out.print(encoding + "\t" + s + "\t"); byte[] barr = s.getBytes(encoding); for (int i = 0; i < barr.length; i++) { int n = barr[i] & 0xFF; String hex = Integer.toHexString(n); if (hex.length() == 1) { System.out.print('0'); } System.out.print(hex); } System.out.println(); } 

如果UTF-8的编码字节在每个平台上都不同(它应该是c2bf ),那么这是编译器问题。

如果是编译器问题,请将“¿”替换为“\ u00bf” 。

由于编辑器和编译器编码,很难确切知道源代码包含哪些字节,或者调用getBytes()的字符串。

你能制作一个简短但完整的程序,只包含ASCII(以及字符串中相关的\ uxxxx转义)仍能显示问题吗?

我怀疑问题可能出在Windows或Linux上的控制台输出上,但最好先获得可重现的程序。