根本原因是JVM默认编码与终端实际编码不一致:Windows默认GBK而JDK常误判,macOS/Linux多用UTF-8;需统一终端编码、JVM参数(-Dfile.encoding=UTF-8)、IDE文件编码设置,并注意Scanner需显式指定UTF-8编码。

Java控制台输出中文显示为问号或方块
根本原因是 JVM 启动时默认编码与终端实际编码不一致,尤其在 Windows 的 CMD/PowerShell 和 macOS/Linux 的 Terminal 中表现不同。Windows 默认是 GBK,而 JDK 8+ 在非 Windows 系统上通常按 UTF-8 推断,但 Windows 上 JDK 常误判为 MS932 或直接 fallback 到 Cp1252。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 先确认终端当前编码:
chcp(Windows CMD)、locale(macOS/Linux) - 再检查 Java 实际用的编码:
System.getProperty("file.encoding"),运行时打印它,别只信 IDE 控制台设置 - 避免在代码里硬写
new String(bytes, "GBK")来“修复”输出——这是掩耳盗铃,源头没对齐,后面 IO、日志、网络全会出问题
IDEA 或 Eclipse 控制台乱码,改了 VM options 没用
IDE 自带的运行终端(Run Console)不完全继承系统环境变量,而是依赖 IDE 自身的编码配置 + JVM 启动参数双重控制。光加 -Dfile.encoding=UTF-8 不够,IDE 还可能覆盖 stdout 的字符集处理逻辑。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- IntelliJ IDEA:进入
Help → Edit Custom VM Options...,添加-Dfile.encoding=UTF-8;再打开Settings → Editor → File Encodings,把Global Encoding、Project Encoding、Default encoding for properties files全设成UTF-8 - Eclipse:右键项目 →
Properties → Resource → Text file encoding设为UTF-8;同时在Run Configurations → Arguments → VM arguments加上-Dfile.encoding=UTF-8 - 关键点:改完必须重启 IDE,否则缓存的 Console 输出管道不会重置编码
命令行直接 java -jar 启动 jar 包,中文还是乱码
这时完全脱离 IDE,纯靠系统终端和 JVM 协作。Windows CMD 默认 GBK,但 JDK 17+ 在未显式指定时可能强制用 UTF-8,导致 printf 出来就是乱码;反过来,Linux 终端若 locale 是 en_US.UTF-8,但 jar 包里用了 System.console().readLine(),也可能因 Console 初始化失败返回 null。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- Windows 下优先用 PowerShell 替代 CMD,它对 UTF-8 支持更稳定;启动前执行:
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding - 统一加 JVM 参数:
java -Dfile.encoding=UTF-8 -jar app.jar—— 注意-Dfile.encoding必须在-jar之前,放后面会被忽略 - 如果用批处理(.bat)启动,第一行加
@chcp 65001 >nul(激活 UTF-8 Code Page),否则chcp不生效
System.out.println() 正常,但 Scanner.nextLine() 读中文就卡住或截断
这不是编码问题,是 Scanner 内部缓冲区与终端换行符解析错位。常见于 Windows 下用 \r\n 结尾,但 Scanner 在非默认编码下可能把 \r 当作分隔符提前切掉,导致下一次 nextLine() 立即返回空字符串。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 不用
Scanner读控制台输入,改用BufferedReader+InputStreamReader(System.in, "UTF-8") - 或者确保 Scanner 构造时指定编码:
new Scanner(System.in, "UTF-8")(JDK 7+ 支持) - 避免混用:
next()和nextLine()连续调用,前者不消费换行符,后者会立刻读到空行——这和编码无关,但常被误认为是乱码
最麻烦的情况是:你改完了所有配置,System.getProperty("file.encoding") 也打印出 UTF-8,但某台老 Windows 机器上还是乱码。这时候得查具体 JDK 版本——JDK 8u291 之前,Windows 上 -Dfile.encoding 对 System.console() 无效,只能换 JDK 或绕开 Console API。这种细节,文档里不写,搜错误信息也找不到,只能实测。










