UTF-8字符集在Windows Hotspot JVM 1.8.0_201中输出无效编码
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UTF-8字符集在Windows Hotspot JVM 1.8.0_201中输出无效编码相关的知识,希望对你有一定的参考价值。
对不起,如果这是一个愚蠢的问题,我可能会遗漏一些基本的东西。
我只是尝试使用UTF-8编码一个字符串。遵循最佳实践,我不认为默认字符集是UTF-8,因此我使用:
"Ñ".getBytes(Charset.forName("UTF-8"))
根据official Unicode spec,这应该是:0xc391
但是,我得到的是:0xc383e28098
。
我没有理解这一点。无论我是否设置-Dfile.encoding=UTF-8
,都会发生这种情况。
奇怪的是,当我没有指定charset(或使用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
您的代码没有任何问题。问题是编译器如何处理源代码。
当您在代码中编写"Ñ"
并保存文件时,实际写入源文件的字节数是多少?
您似乎将源文件保存为UTF-8文件(这通常是一个不错的选择)。这意味着"Ñ"
被写为UTF-8字节0xC3 0x91。
如果你要在除Windows之外的任何操作系统上编译它,系统的默认编码是UTF-8,那么事情就会像你期望的那样构建和运行。
但是当你在Windows上构建系统的默认字符集是windows-1252时,源文件中的那两个字节会得到不同的处理。编译器使用windows-1252解释这两个字节。无论代码在编辑器中是什么样子,编译器都会看到0xC3 0x91,并将每个字节视为windows-1252 character。在windows-1252中,这些字节代表:
- 0xC3→
Ã
(LATIN CAPITAL LETTER A WITH TILDE) - 0x91→
‘
(LEFT SINGLE QUOTATION MARK)
因此编译器将您的字符串常量编译为“”Ã'“。
所有这些翻译仅在编译时进行。在编译的.class文件中,所有字符串常量都以相同的方式表示;有关源如何编码的任何信息都将丢失。在运行时,Java只知道您(显然)已将您的字符串编译为"Ñ"
。
在运行时,当您使用UTF-8解码该双字符字符串时,您将获得这两个字符的UTF-8字节序列:
Ã
→0xc3 0x83‘
→0xe2 0x80 0x98
正如您所推测的那样,解决方案是告诉编译器您的源文件是UTF-8,因此它将字节0xc3 0x91解释为Ñ
。
以上是关于UTF-8字符集在Windows Hotspot JVM 1.8.0_201中输出无效编码的主要内容,如果未能解决你的问题,请参考以下文章
Apache Cassandra安装错误Windows 10:hotspot_compiler
如何在 Windows 上使用不属于 UTF-8 的字符创建文件名?