【问题标题】:UTF-8 charset outputs invalid encoding in Windows Hotspot JVM 1.8.0_201UTF-8 字符集在 Windows Hotspot JVM 1.8.0_201 中输出无效编码
【发布时间】:2019-03-17 16:48:28
【问题描述】:

对不起,如果这是一个愚蠢的问题,我可能在这里遗漏了一些基本的东西。

我只是想使用 UTF-8 对字符串进行编码。遵循最佳实践,我不假设默认字符集是 UTF-8,因此我使用:

"Ñ".getBytes(Charset.forName("UTF-8"))

根据official Unicode spec,这应该是:0xc391

但是,我得到的是:0xc383e28098

我无法理解这一点。无论我是否设置-Dfile.encoding=UTF-8,都会发生这种情况。

奇怪的是,当我指定字符集(或使用Charset.defaultCharset())时,使用windows-1252编码,输出正确编码为UTF-8!

更重要的是,当我通过 IntelliJ 而不是命令行运行代码时,UTF-8 字符集实际上可以按预期工作。 IntelliJ 在类路径中添加了很多不相关的库,所以我猜其中一个负责更正,但我希望它能够在生产中工作。

我的java -version

java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) Client VM (build 25.201-b09, mixed mode

【问题讨论】:

  • byte[] 数组到0xc383e28098 十六进制值(进一步的Java 代码、文件、十六进制编辑器...),您究竟做了什么? Java中的字节数组有多长?
  • @CarlosHeuberger 为什么重要?我使用字符串文字,不必关心 Java 在内部使用什么编码,它应该正确编码代码点。我还尝试将字符串文字输入为 UTF-8 字节数组,对其进行解码和重新编码,并获得完全相同的结果。无论如何我都会尝试 javac,但我不明白它为什么会有所帮助......
  • @RalfKleberhoff 我只是将字节保存到一个文件中,然后使用十六进制编辑器打开它,使用java.nio.file.Files.write(Path, byte[])
  • @CarlosHeuberger 实际上,"Ñ" 将写作"\u00d1"。 ("\uc391"Hangul syllable。)
  • @CarlosHeuberger "\uc391".getBytes("UTF-8") 不会产生该输出。

标签: java unicode utf-8 character-encoding


【解决方案1】:

您的代码没有任何问题。问题在于编译器如何处理你的源代码。

当您在代码中写入"Ñ" 并保存文件时,实际将哪些字节写入源文件?

您似乎将源文件保存为 UTF-8 文件(这通常是一个不错的选择)。这意味着"Ñ" 已作为 UTF-8 字节 0xC3 0x91 写入文件。

如果您要在 Windows 以外的任何操作系统(系统的默认编码为 UTF-8)上编译它,一切都会完全按照您的预期构建和运行。

但是当你在 Windows 上构建时,系统的默认字符集是 windows-1252,源文件中的这两个字节会得到不同的处理。编译器使用 windows-1252 解释这两个字节。无论代码在您的编辑器中是什么样子,编译器都会看到 0xC3 0x91 并将每个字节视为windows-1252 character。在 windows-1252 中,这些字节表示:

因此编译器会将您的字符串常量编译为 `"Ã'"。

所有这些翻译仅在编译时进行。在编译的 .class 文件中,所有字符串常量都以相同的方式表示;有关源如何编码的任何信息都会丢失。在运行时,Java 只知道您已经(显然)将您的字符串编译为 "Ñ"

在运行时,当您使用 UTF-8 解码该两个字符的字符串时,您将获得这两个字符的 UTF-8 字节序列:

  • Ã → 0xc3 0x83
  • → 0xe2 0x80 0x98

正如您所推测的,解决方案是告诉编译器您的源文件是 UTF-8 格式,因此它将字节 0xc3 0x91 解释为 Ñ

【讨论】:

  • 这简直是疯了......我可以发誓我试图直接使用字节数组和 unicode 文字 (\u00d1) 并且它没有工作......这只会让事情变得更加复杂我,因为字符串文字只是我的一个例子 - 我在生产环境中看到这种行为,其中通过线路接收的字符串被序列化......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
  • 2015-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-14
相关资源
最近更新 更多