理解字符串编码/解码Java

Posted

技术标签:

【中文标题】理解字符串编码/解码Java【英文标题】:Understanding String encoding/decoding Java 【发布时间】:2016-06-17 03:19:45 【问题描述】:

我有一个使用 mvn exec:java 运行的程序(我的主文件以 utf-8 编码,系统的默认字符集是 windows-1252)

System.out.println(Charset.defaultCharset()); //print windows-1252
String s = "éàè";
System.out.println(new String(s.getBytes(Charset.forName("UTF-8")))); //OK Print éàè
System.out.println(new String(s.getBytes(Charset.forName("windows-1252")))); //Not OK Print ▒▒▒

我不明白为什么第一次打印有效,根据文档 getBytes 使用给定的字符集将字符串编码为字节序列,并且字符串构造函数构造一个新字符串使用平台的默认字符集解码指定的字节数组

所以第一次打印以 UTF-8 编码,然后使用平台的默认字符集 windows-1252 进行解码,这怎么可能?它无法使用平台字符集 windows-1252 解码编码的 utf-8 字节数组。

第二个打印错误,我不明白为什么。由于我的文件以 utf-8 编码并且平台字符集是 windows-1252,我的意图是使用 windows-1252 字符集对字符串进行编码,因此我调用 s.getBytes(Charset.forName("windows-1252")) 然后使用先前的结果创建一个字符串,但它不起作用

【问题讨论】:

试试PrintStream out = new PrintStream(System.out, true, "windows-1252"); out.println(s); 附带说明,MS-DOS 默认字符集不是 1252,请参见此处:docs.oracle.com/javase/7/docs/technotes/guides/intl/… PrintStream out = new PrintStream(System.out, true, "windows-1252");不起作用,但 PrintStream out = new PrintStream(System.out, true, "utf-8");没有 @Berger 你是对的,我正在使用 MinGW 执行我的程序,使用 MS-DOS 程序可以正常工作 【参考方案1】:

Stringéàè 在 UTF-8 中编码为字节八位字节 0xC3 0xA9 0xC3 0xA0 0xC3 0xA8。解释为 Windows-1252 的相同字节八位字节是字符串值 éÃ<nbsp>è(其中 <nbsp>不间断空格 字符,Unicode 代码点 U+00A0)。

在第一个示例中,您将 String 转换为上述 UTF-8 字节,然后使用 Windows-1252 而不是 UTF-8 将字节转换回 String。所以你应该得到一个新的StringéÃ<nbsp>è,而不是éàè。然后您将 String 写入控制台,因此它使用 Windows-1252 编码回字节八位字节 0xC3 0xA9 0xC3 0xA0 0xC3 0xA8,如果控制台正在显示字节,则应显示为 éÃ<nbsp>è(或类似的东西)原样。另一方面,如果将控制台配置为 UTF-8,则当解释为 UTF-8 时,这些字节将显示为 éàè

在第二个示例中,由于您使用 Windows-1252 进行编码和解码,并且 Windows-1252 支持所讨论的特定字符,因此您应该在编写之前以原始 Stringéàè 结束它到控制台。如果 String 使用 Windows-1252 编码为字节,并且控制台配置为 UTF-8,那么为什么您看不到 éàè 显示是有道理的。 Stringéàè 在 Windows-1252 中编码为字节八位字节 0xE9 0xE0 0xE8,这不是有效的 UTF-8 字节八位字节序列。

简而言之,当您的控制台配置为将传出字节解释为 UTF-8 时,您所看到的行为会发生,但您没有为其提供正确的 UTF-8 编码字节作为输出。

【讨论】:

这是对问题的重述,而不是答案。如果您断言他的控制台设置为 UTF-8,那么您应该先这样做。 我不只是重申这个问题。问题是要求了解编码的行为与预期有何不同。我想我已经回答了。 莱德被埋葬了。现在有了最后一段就更有意义了。 确切的@RemyLebeau,我忘了考虑控制台的编码。实际上,无论我使用 MinGW 控制台还是 MS-DOS,结果都不同

以上是关于理解字符串编码/解码Java的主要内容,如果未能解决你的问题,请参考以下文章

尝试在已用 Java 编码的 JS 中解码 Base64 时出现“要解码的字符串未正确编码”错误

JAVA编码字符串和解码字符串

编码/解码有啥区别?

编码/解码有啥区别?

Java核心类库-IO-字符解码和编码操作

Java编码问题