Java 17+ 在 Windows 平台输出 Unicode 字符显示问号的原因与解决方案

Java 17+ 在 Windows 平台输出 Unicode 字符,会显示问号,本文将介绍该现象的原因与解决方案。

问题描述

当使用 Unicode 字符输出到 Windows 平台时,会显示问号,如下图所示(此处使用 Java 21):

1
System.out.println("\uD83D\uDE02");

一个问号,意味着可能出现了编码问题

原因分析

Java 18 实现了一个改动,JEP 400: UTF-8 by Default

Specify UTF-8 as the default charset of the standard Java APIs. With this change, APIs that depend upon the default charset will behave consistently across all implementations, operating systems, locales, and configurations.

看起来不错,但是该变动的目标之一是:

Standardize on UTF-8 throughout the standard Java APIs, except for console I/O.

我们的控制台编码是 UTF-8,但是 PrintStream 仍然使用默认编码向控制台输出内容,在 Windows 平台这可能是 GBK 或 Windows-1252 编码。

另外,可以在 debug 中查看 ((OutputStreamWriter) System.out.textOut.out).se.cs 确认输出编码。

在这篇回答[1]中可以更看到详细的讨论。

解决方案

  1. 降级 Java 版本至 17 及以下。
  2. 设置控制台输出字符集为 UTF-8 编码。
1
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, StandardCharsets.UTF_8));

问题解决了

References


Java 17+ 在 Windows 平台输出 Unicode 字符显示问号的原因与解决方案
https://blog.zhanganzhi.com/zh-CN/2024/04/bb7bc15fe041/
作者
Andy Zhang
发布于
2024年4月11日
许可协议