首页 > 其他分享 >JDK 18 及以上使用标准输出流中文输出乱码问题

JDK 18 及以上使用标准输出流中文输出乱码问题

时间:2024-12-08 16:54:48浏览次数:2  
标签:输出 UTF JDK encoding System 乱码 println getProperty out

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
链接: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 即可设置输出流的编码。

参考


End

标签:输出,UTF,JDK,encoding,System,乱码,println,getProperty,out
From: https://www.cnblogs.com/stazxr/p/18593533

相关文章

  • C语言的常用标准数据类型、转义字符、输出格式符、输入格式符、算术运算符、关系运算
    目录 C语言的常用标准数据类型C语言的常用转义字符C语言的输出格式符C语言的输入格式符C语言的算术运算符C语言的关系运算符C语言的逻辑运算符 C语言的常用标准数据类型C语言的常用转义字符‘\n’       换行符‘\t’       制表符‘\b’ ......
  • vscode怎么配置java jdk 1.8(jdk如何配置在windows)
    首先我想说高版本Vscode不支持jdk8,所以需要配置文件。1.安装jdkjavaJDK1.8版本下载_jdk1.8下载资源-CSDN文库首先都会去确认JDK的安装是否正确,两个命令缺一不可。打开‘cmd’--> java-version,javac-version安装JDK选择安装目录安装过程中会出现两次安装提示。第......
  • printf返回值有意义吗?输入输出返回值?NSLog和printf的区别?%a和%A格式串?%l %h和%d %o %
    printf返回值有意义吗?利用man3printf获取返回值的解释:Uponsuccessfulreturn,thesefunctionsreturnthenumberofcharactersprinted(excludingthenullbyteusedtoendoutputtostrings).这里提到是返回被成功输出的字符个数,这里的字符特指字节。一般......
  • 根据后序遍历完全二叉树构建树并输出中序遍历
    来看这道题:之前编者想了很久,该如何仅根据后序序列建树,在反复研磨遍历的特征后,我突然发现:对于完全二叉树,我们完全可以采用其在线性表示(用数组)的性质解题性质:根节点x, 左子树索引为2x,右子树索引为2x+1且不为空。则,我们只需按后序遍历的特点递归建树即可。上代码:......
  • 输出与文件编码的兼容性 在 .CMD 文件中,通过正确的编码方式(如 UTF-8),可以确保脚本与外
    在计算机科学和技术领域,.CMD和.BAT文件都属于批处理脚本文件格式,它们是Windows操作系统中用于执行命令的一种文件类型。虽然这两者非常相似,但.CMD文件有一些相对于.BAT文件的优势,特别是在Windows2000及以后版本中。下面将分析.CMD文件相对于.BAT文件的一些优势,并......
  • JDK1.8
    JDK1.81.Lamdba表达式Lambda表达式是什么?Lambda是一个匿名函数,我们可以将Lambda表达式理解为一段可以传递的代码(将代码像数据一样传递)。使用它可以写出简洁、灵活的代码。作为一种更紧凑的代码风格,使java语言表达能力得到提升。publicstaticvoidmain(String[]args)......
  • [码码哈哈]2024-12月最新JDK8、11、17、21国内免登录快速下载
    现有LTS版本截至2024年,JDK的LTS版本包括:JDK8(发布于2014年3月):这是一个非常流行的LTS版本,很多老旧系统仍在使用。JDK11(发布于2018年9月):引入了一些新特性和改进,并成为许多企业的首选。JDK17(发布于2021年9月):提供了对Java语言和平台的一系列增强和改......
  • gorm: 配置日志输出到文件
    一,官方文档地址:https://gorm.io/zh_CN/docs/logger.html二,代码例子:1,写日志到文件的函数://日志写入到文件funcLogToFile(filename,msgstring){ //输出到文件 //filename:="logs/"+time.Now().Format("2006-01-02")+".log" file,err:=os.OpenFile(file......
  • TIM输出比较---STM
    一、简介TIM定时器:OC输出比较输出比较可以通过比较CNT与CCR寄存器(捕获/比较寄存器)值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形;每个高级定时器和通用定时器都拥有4个输出比较通道;高级定时器的前3个通道额外拥有死区生成和互补输出的功......
  • ollama 0.5.0 发布内置结构化输出了
    就在前几天ollama发布了0.5.0了内置支持结构化输出了,同时ollamapython以及js库已经支持此特性了,很值得使用说明同时就在一个小时之前发布了0.5.1解决了一些结构化输出的bug参考资料https://github.com/ollama/ollama/releases/tag/v0.5.0https://github.com/ollama/olla......