JDK 18 及以上运用规范输出流中文输出乱码问题
著作权归作者一切。
商业转载请联络作者取得授权,非商业转载请注明出处。
链接:https://stazxr.cn/2024/12/05/JDK-18-以上运用规范输出流中文输出乱码问题/
来历:終わり群星
问题描绘
原因是 tomcat 调用servlet输出的System.out.println
(也便是所说的操控台输出流)中文乱码,可是其他输出没有受到影响。
问题剖析
运转环境:JDK 21, Tomcat 10
我一切的代码都是UTF-8编码的,而且在IDEA中设置了UTF-8编码。
而且Tomcat也装备了-Dfile.encoding=UTF-8
选项
经过检查System.out
的编码办法,发现是GBK
,可是在操控台的编码办法是UTF-8
。
System.out.println(System.out.charset()); // System.out.charset()办法自jdk18起
// output: GBK
运用jdk17的时分没有问题,可是运用jdk21就会呈现乱码问题。
处理方案
参阅JEP 400: UTF-8 by Default (openjdk.org)经过调用getProperty办法获取默许字符集
System.out.println("Java Runtime version " + System.getProperty("java.runtime.version"));
System.out.println("----------------------------------------------------------");
//大局默许编码 JDK21是UTF
System.out.println("Charset.defaultCharset() = " + Charset.defaultCharset());
//默许文件的编码,这个应该是字节码文件
System.out.println("System.getProperty(\"file.encoding\") = " + Charset.defaultCharset().displayName());
//获取的是本地的字符集编码,中文windows体系应该是GBK
System.out.println("System.getProperty(\"native.encoding\") = " + System.getProperty("native.encoding"));
System.out.println("System.getProperty(\"sun.jnu.encoding\") = " + System.getProperty("sun.jnu.encoding"));
//这个是输出流的默许字符集编码
System.out.println("System.getProperty(\"sun.stdout.encoding\") = " + System.getProperty("sun.stdout.encoding"));
//这个是过错流的默许编码
System.out.println("System.getProperty(\"sun.stderr.encoding\") = " + System.getProperty("sun.stderr.encoding"));
//console默许编码
System.out.println("System.console().charset() = " + System.console().charset());
//当时输出流的编码
System.out.println("System.out.charset() = " + System.out.charset());
System.out.println("----------------------------------------------------------");
在一般的情况下System.getProperty("sun.stdout.encoding")
和System.getProperty("sun.stderr.encoding")
的值是UTF-8
,可是在Tomcat中是null
。
tomcat 10 不会指定输出流的字符编码
所以咱们需要在发动tomcat的时分指定输出流的字符编码
是在发动装备中的 VM options 增加参数:
-Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8
这种办法只能处理所设置程序的编码问题,若需处理 Javadoc 的乱码,则需在-D前增加-J。
-J-Dstdout.encoding=UTF-8 -J-Dstderr.encoding=UTF-8
总结
乱码问题只呈现在jdk18及以上的版别,由于Java 18 中将默许编码改为了 UTF-8,但没有改动System.out和System.err的编码。
所以运用jdk17没有问题,可是在运用jdk21就会呈现乱码问题。
只要在 VM options 中增加 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8
即可设置输出流的编码。
参阅
- JEP 400: UTF-8 by Default (openjdk.org)
- https://openjdk.java.net/jeps/400
- 处理 Java 18 以上 IDEA 中文输出乱码问题(知乎)
- 处理IDEA操控台中输出中文乱码并探求原因(JDK18及以上)