You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java从System.in读取带重音字符异常的问题排查求助

Windows控制台Java读取重音字符异常问题排查与解决

问题背景

开发需从控制台读取含重音字符的Java应用时,发现现代控制台(如Windows Terminal中的PowerShell)本身可正确处理重音字符输入输出:

PS C:\> echo ?
ü
Ps C:\>

注:该行为在单独的命令提示符中无法复现;但在Windows Terminal中运行命令提示符时,发送前即可正确显示重音字符。

但运行测试代码时出现异常,输入的重音字符字节数组输出全为0。测试代码如下:

package com.test.outputtest;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.nio.file.*;

public class OutputTest {

    public static void main(String[] args) {
        // Set I/O to use UTF-8
        System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, StandardCharsets.UTF_8));

        // Create the response listener
        Scanner input = new Scanner(System.in, StandardCharsets.UTF_8);

        System.out.println(Arrays.toString("èéëê".getBytes(StandardCharsets.UTF_8)));
        String temp = input.nextLine();
        System.out.println(Arrays.toString(temp.getBytes(StandardCharsets.UTF_8)));
    }

}

生成app.jar后,在PowerShell执行命令及输出:

PS C:\Users\[name]\Desktop\output_test> chcp 65001
Active code page: 65001
PS C:\Users\[name]\Desktop\output_test> java "-Dfile.encoding=UTF-8" -jar app.jar
[-61, -88, -61, -87, -61, -85, -61, -86]
èéëê
[0, 0, 0, 0]

尝试用Console替代Scanner问题依旧;IntelliJ终端中运行正常,但命令提示符或PowerShell中均报错。

环境信息:

  • 操作系统: Windows 10 build 19045.2728
  • Java版本: 17.0.6(IntelliJ中使用同版本)
  • 默认代码页: 850(OEM)
  • 测试时代码页: 65001(UTF-8)

问题原因

Windows控制台的UTF-8支持存在历史兼容问题,Java处理控制台输入流时,即使指定UTF-8编码,也可能因底层Windows API的编码映射机制出错;同时手动替换System.out的PrintStream会干扰控制台编码一致性。

解决方案

1. 移除手动替换System.out的代码

删除代码中手动设置System.out的行,依赖JVM参数统一编码:

// 移除该行代码
// System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, StandardCharsets.UTF_8));

启动命令保持java "-Dfile.encoding=UTF-8" -jar app.jar,JVM会统一处理标准输入输出的编码。

2. 开启Windows原生UTF-8全局支持

修改系统设置让控制台默认使用UTF-8:

  • 打开「设置」→「时间和语言」→「语言」→「管理语言设置」→「更改系统区域设置」
  • 勾选「Beta版:使用UTF-8提供全球语言支持」,重启系统
    此设置无需手动执行chcp 65001,同时解决Java输入的编码映射问题。

3. 临时兼容方案(不推荐长期使用)

若无法修改系统设置,可临时切换到ANSI编码规避问题:

  • 执行chcp 1252切换编码
  • 修改代码中Scanner的编码为StandardCharsets.ISO_8859_1
    注意:UTF-8是现代本地化标准,长期使用ANSI会限制多语言字符支持。

4. 正确使用Console类

使用Console类直接读取字符,避免编码转换错误:

Console console = System.console();
if (console != null) {
    String input = console.readLine();
    System.out.println(Arrays.toString(input.getBytes(StandardCharsets.UTF_8)));
}

验证

修改代码后重新打包,在PowerShell执行启动命令,输入重音字符后,输出的字节数组应与预定义字符串的字节数组一致(如输入èéëê会输出[-61, -88, -61, -87, -61, -85, -61, -86])。

内容的提问来源于stack exchange,提问作者ShadeOfLight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:12:51