摘要:本文系统讲解 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: 增强交互,适合终端工具。