一文掌握 Java 键盘输入:从入门到高阶(含完整示例与避坑指南)

摘要:本文系统讲解 Java 中的键盘输入。围绕 System.in 的三条主线 —— Scanner、BufferedReader + InputStreamReader、Console —— 从原理、用法、编码与本地化、常见坑到测试与封装,帮助你在各种场景下正确、稳健地处理输入。

一、为何要理解“键盘输入”的底层模型

底层只有一个输入源: ystem.in,类型是 InputStream(字节流)。

字符与字节的桥梁: 文本输入需要通过 字符集解码 才能得到 char/String。

API 的差异:

Scanner:易用,自动分隔并解析。

BufferedReader:高效,逐行读取,可控性强。

Console:增强交互体验,支持密码输入。

理解这些,能帮你在不同场景下选择合适的方案。

二、三种主流方案概览

方案核心类优点适用场景注意点Scannerjava.util.Scanner上手快,支持各种类型日常开发、教学作业正则切分偏慢;行尾换行问题BufferedReaderBufferedReader + InputStreamReader高效,编码可控性能敏感、大量输入需手动解析数字Consolejava.io.Console支持无回显密码真终端交互IDE 中可能为 null

三、Scanner:最常用也最易踩坑的方案

1. 基本用法

import java.util.*;

public class ScannerDemo {

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

System.out.print("请输入 姓名 年龄 身高:");

String name = sc.next();

int age = sc.nextInt();

double height = sc.nextDouble();

System.out.println("name=" + name + ", age=" + age + ", height=" + height);

}

}

默认分隔符:空白字符。

可自定义分隔符:sc.useDelimiter(“,”)。

读整行:sc.nextLine()。

读单字符:sc.next().charAt(0)。

2. 健壮性输入

while (true) {

System.out.print("请输入一个整数:");

if (sc.hasNextInt()) {

int n = sc.nextInt();

sc.nextLine(); // 吃掉换行

break;

} else {

System.out.println("输入错误,请重试!");

sc.nextLine(); // 丢弃错误输入

}

}

3. 常见坑

换行问题: nextInt() 后跟 nextLine() → 会读到空串。

Locale 影响小数点: 用 sc.useLocale(Locale.US) 固定为 .。

不要关闭 Scanner: 否则会关掉底层 System.in。

四、BufferedReader + InputStreamReader:高效可控的选择

1. 逐行读取

BufferedReader br = new BufferedReader(

new InputStreamReader(System.in, StandardCharsets.UTF_8)

);

String line;

while ((line = br.readLine()) != null) {

System.out.println("读到:" + line);

}

readLine():返回整行(不含换行符);EOF 返回 null。

显式指定编码(如 UTF-8)以避免乱码。

2. 快读模板(竞赛常用)

static class FastScanner {

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

StringTokenizer st;

String next() throws IOException {

while (st == null || !st.hasMoreTokens()) {

String line = br.readLine();

if (line == null) return null;

st = new StringTokenizer(line);

}

return st.nextToken();

}

int nextInt() throws IOException { return Integer.parseInt(next()); }

}

特点:比 Scanner 更快,适合大数据量。

五、Console:真正的控制台交互

Console cons = System.console();

if (cons == null) {

System.err.println("No console available");

return;

}

String user = cons.readLine("用户名: ");

char[] pwd = cons.readPassword("密码: ");

可隐藏密码输入(不回显)。

在 IDE 中常返回 null,需在终端运行 java 命令。

六、编码、Locale 与行结束符

编码: Scanner 默认平台编码;推荐 BufferedReader + UTF-8。

Locale: Scanner 解析小数受 Locale 影响;统一用 Locale.US。

行结束符: readLine() 和 Scanner 已屏蔽平台差异(\r\n vs \n)。

七、总结

Scanner: 最方便,适合日常。

BufferedReader: 高效,适合性能敏感场景。

Console: 增强交互,适合终端工具。