著作权归作者所有。

商业转载请联系作者获得授权,非商业转载请注明出处。

链接: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 即可设置输出流的编码。

参考

写在最后

JDK 18 及以上使用标准输出流中文输出乱码问题的更多相关文章

  1. 解决VS Code编译调试中文输出乱码

    最近尝试用VS Code配置了C和C++的编译调试环境,结果遇到了中文输出乱码问题,查阅网上竟然还没有相关问题,有怀疑是mingw中文支持问题,但最后证明是VS Code编码问题. 解决方案: 文件- ...

  2. qtcreator_process_stub中文输出乱码

    使用qt运行程序输出中文,全都变成了□,让人很头疼,百度了很久,找了一些解决方案都是: 用vim打开x11-common,在控制台输入 vim /etc/X11/Xresources/x11-comm ...

  3. 控制台程序的中文输出乱码问题(export LC_CTYPE=zh_CN.GBK,或者修改/etc/sysconfig/i18n为zh_CN.GBK。使用setlocale(LC_CTYPE, "");会使用默认办法。编译器会将源码做转换成Unicode格式,或者指定gcc的输入文件的编码参数-finput-charset=GBK。Linux下应该用wprintf(L"%ls/n",wstr))

    今天发现用securecrt登陆时,gcc编译出错时会出现乱码,但直接在主机的窗口界面下用Shell编译却没有乱码.查看了一下当时的错误描述,发现它的引号是中文引号,导致在SecureCRT中显示出错 ...

  4. python--ulipad控制台中文输出乱码

    ulipad用起来顺手,而不尽人意的地方时,它不能正确输出中文.而且有人指出这和文件的编码没关系,所以将”设置“选项里”缺省文档编码“修改为”utf-8“也无济于事.为了解决这个问题,我在网上搜了搜, ...

  5. Code:Blocks中文输出乱码解决方法

    0x01 问题描述 将CB的编码格式设置为UTF-8之后,在CMD窗口输出中文乱码. 0x02 解决办法 控制台显示的时候缺省的是使用系统默认的字符集,比如windows下用的是GBk,但是默认情况下 ...

  6. Sublime + Python3 + 虚拟环境 + 去除 中文输出乱码

    MacBook Pro Retina 13 2013年底版 所用软件 1. Sublime Text 3安装 Virtualenv package 2. 用 iterm2 .或者终端安装zip:apt ...

  7. windows下解决PyCharm控制台中文输出乱码

    我用的PyCharm是2018.2版本 在调用os.system()的过程中遇到了控制台中文乱码的问题,具体如下 网上说的将两个Encoding格式都设置为UTF-8并没有解决问题,后来我将Proje ...

  8. python3中文输出乱码的问题

    最近使用you-get这个工具下载视频,发现命令行窗口里显示的媒体标题是乱码(但文件管理器里显示正常).我的命令行窗口的code page是936,sys.stdout.encoding是utf-8, ...

  9. Java控制台中输入中文输出乱码的解决办法

    Run---Run Configurations---Common---Encoding---Other---GBK Run Configurations里的Common中将编码方式改成GBK就正常了

  10. Jenkins控制台中文输出乱码解决方法

    1. 设置jenkins所在服务器环境变量,右键我的电脑→属性→高级系统设置→环境变量,添加JAVA_TOOL_OPTIONS 2.修改Tomcat配置,进入apache_tomcat/conf文件夹 ...

随机推荐

  1. JavaScript – 用 Generator 运行异步函数 & await async

    前言 上一篇 JavaScript – Promise 介绍了如何用 JS 编写可读性高的异步函数. 但其实呢, Promise 还不是最好的. 在 es6 之前, Promise 比起回调地狱是好了 ...

  2. MyBatis——快速入门

    MyBatis 快速入门     查询 tb_user 的所有信息   1.创建tb_user表,添加数据 create database mybatis; use mybatis; drop tab ...

  3. 多线程ExecutorService 的理解与使用

    原文链接:https://www.cnblogs.com/gxz-sw/p/6754476.html 接口 Java.util.concurrent.ExecutorService 表述了异步执行的机 ...

  4. docker 安装 elasticsearch 集群

    此处部署为单个服务器启动三个elasticsearch容器 问题:本打算在三个服务器上单独部署elasticsearch 容器,elasticsearch.yml 注册用的宿主机ip,但是容器之间通信 ...

  5. 【赵渝强老师】史上最详细的PostgreSQL体系架构介绍

    PostgreSQL是最像Oracle的开源数据库,我们可以拿Oracle来比较学习它的体系结构,比较容易理解.PostgreSQL的主要结构如下: 一.存储结构 PG数据存储结构分为:逻辑存储结构和 ...

  6. GitLab +Jenkins + WebHook配置自动发版

    1.jenkins安装插件 需要安装插件:Gitlab Hook Plugin和Gitlab Plugin 2.Jenkins配置job 复制这里的url,需要在后面gitlab的配置中使用到. 基本 ...

  7. 工作使用:Exchange命令集(超级重要)

    工作使用:Exchange命令集(超级重要) 命令1:导出某个用户的邮件                  New-MailboxExportRequest   -mailbox  dusonglin ...

  8. 云原生爱好者周刊:KubeKey v2.1.0 alpha 版发布!

    KubeKey v2.1.0-alpha.0 发布啦!该版本的主要特性: 支持三种使用场景的 Etcd 集群(二进制部署,Kubeadm 部署,连接外置已存在的 Etcd 集群). 支持部署 Cont ...

  9. 一文彻底搞定Redis与MySQL的数据同步

    Redis 和 MySQL 一致性问题是企业级应用中常见的挑战之一,特别是在高并发.高可用的场景下.由于 Redis 是内存型数据库,具备极高的读写速度,而 MySQL 作为持久化数据库,通常用于数据 ...

  10. vue之JavaScript封装

    导入js文件有很多种方式,我喜欢使用这种,感觉跟框架导入很相似.没有多余的沉湎. 定义一个js文件,比如util.js import Vue from "vue"; //===== ...