0%

从jshell乱码谈终端字符集

jshell 是个好东西,一些小的 Java 实验不用再写完整的代码测试了。

但是,在使用 jshell 过程中,笔者遇到了中文乱码的问题。终端执行 jshell 命令,可见回显的信息即会显示乱码,如下:

1
2
3
#EZ> jshell
|  ��ӭʹ�� JShell -- �汾 13.0.2
|  Ҫ�����˽�ð汾, �����: /help intro

简单来说应该是终端字符集与 Java 默认字符集不匹配导致的。

笔者在 Windows 下使用 PowerShell。按理说,终端默认字符集应该是 GBK,而 Java 默认字符集也应该是 GBK——一致的话是不应该出现乱码的。

怎么回事呢?那就分别查看一下终端与 Java 使用的字符集都是什么吧!

在 jshell 命令模式下,使用下面的命令查看 Java 默认字符集:

1
2
jshell> java.nio.charset.Charset.defaultCharset()
$1 ==> GBK

可见使用的是 GBK,符合预期。再来看下终端本身的字符集是什么:

1
2
#EZ> chcp 
活动代码页: 65001

65001 代表的是 UTF-8,与预期不符。

因此,由于终端与 Java 使用的字符集不一致,所以导致 jshell 中文乱码。

要解决乱码,就是要把一端的字符集改为跟另一端一致即可。如果没有特殊要求,我们可以调整任意一端。修改终端字符集可以用以下命令之一:

1
2
[System.Console]::OutputEncoding=[System.Text.Encoding]::GetEncoding(936) 
chcp 936

936 代表 GBK。

或者,通过环境变量指定 Java 的字符集:

1
$env:JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8"

需要注意的是,以上命令都是当前环境有效的,即是说关闭终端,字符集设置即失效了。

如果想要长期有效,可以将命令写在 PowerShell 的 PROFILE 文件中,使得启动终端时初始化设置字符集。或者使用命令修改环境变量,如下:

1
[System.Environment]::SetEnvironmentVariable("JAVA_TOOL_OPTIONS", "-Dfile.encoding=UTF8", "User")

参考

Microsoft Docs:代码页标识符