控制台输入中文乱码的本质是读取编码与控制台实际编码不一致;需用InputStreamReader显式指定对应编码(如GBK或UTF-8)包装System.in,再通过BufferedReader或Scanner读取,才能正确解析中文。

控制台输入中文乱码,本质是编码不一致:Java 默认用系统默认编码读取输入流,而 Windows 控制台(cmd)通常用 GBK,IDE(如 IntelliJ 或 Eclipse)的终端可能设为 UTF-8,但标准输入流 System.in 本身无编码信息,必须显式指定解码方式。使用 InputStreamReader 包装 System.in 并传入正确字符集,就能准确解析中文。
确认当前控制台的实际编码
乱码根源在“读取时用的编码”和“控制台输出时用的编码”不匹配。需先查清环境:
- Windows cmd 中执行
chcp,显示类似活动代码页: 936→ 对应 GBK - Windows Terminal 或某些 IDE 内置终端可能设为 UTF-8(代码页 65001)
- macOS/Linux 终端一般默认 UTF-8
- IntelliJ:File → Settings → Editor → File Encodings → “Terminal Encoding” 查看
用 InputStreamReader 指定编码读取
不要直接用 Scanner(System.in)(它依赖平台默认编码),而是显式构造带编码的 InputStreamReader:
InputStreamReader reader = new InputStreamReader(System.in, "GBK"); // Windows cmd // 或 InputStreamReader reader = new InputStreamReader(System.in, "UTF-8"); // Windows Terminal / macOS / Linux / IDE UTF-8 环境 BufferedReader br = new BufferedReader(reader); String line = br.readLine(); // 此时 line 中文正常
⚠️ 注意:"GBK" 和 "UTF-8" 是字符串字面量,大小写不敏感,但推荐全大写;若编码名错误会抛 UnsupportedEncodingException,建议捕获或用 StandardCharsets(Java 7+)更安全:
InputStreamReader reader = new InputStreamReader(System.in, StandardCharsets.UTF_8);
配合 Scanner 使用(保持习惯又不失控)
如果仍想用 Scanner 的便利方法(如 nextLine()、nextInt()),可将带编码的 InputStreamReader 传给 Scanner 构造器:
Scanner scanner = new Scanner(new InputStreamReader(System.in, StandardCharsets.UTF_8)); String name = scanner.nextLine(); // 中文输入不再乱码 int age = scanner.nextInt(); // 数值类方法也正常
这样既保留了 Scanner 的易用性,又绕过了其默认编码陷阱。
避免常见坑
- 不要写
new InputStreamReader(System.in)(无参构造),它调用Charset.defaultCharset(),常与控制台实际编码不符 - 不同运行环境编码可能不同:同一份代码,在 cmd 下用
GBK,在 IDEA 终端中可能要用UTF-8—— 建议根据部署环境统一配置,或通过启动参数动态指定 - 如果程序打包成 jar 后双击运行,Windows 会用
java.exe启动,默认关联控制台编码仍是 GBK;若用javaw.exe则无控制台,不涉及此问题 - 测试时尽量在目标环境中运行,而非仅依赖 IDE 运行配置
核心就一句话:让 InputStreamReader 知道控制台此刻用的是什么编码,它才能把字节正确翻译成中文字符。对得准,就不乱。


















