1. 方法定义
System.in
是 Java 标准库中的静态常量:
public static final InputStream in
作为字节输入流 (InputStream
),提供读取原始字节的方法:
int read()
:读取单个字节(0-255),流结束返回-1
int read(byte[] b)
:读取字节到数组,返回实际读取字节数int read(byte[] b, int off, int len)
:读取指定长度的字节到数组偏移位置
2. 功能说明
- 数据来源:默认关联命令行/控制台输入
- 流特性:
- 阻塞式:等待用户输入(程序暂停直到回车)
- 字节导向:需手动处理字符编码
- 典型用途:控制台程序、命令行工具交互
3. 示例代码
(1) 基础字节读取
System.out.print("输入字符: ");
int byteData = System.in.read(); // 读取单个字节
System.out.println("ASCII值: " + byteData);
(2) 读取整行文本(推荐)
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ConsoleReader {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("请输入姓名: ");
String name = reader.readLine(); // 读取整行
System.out.println("你好, " + name + "!");
}
}
(3) 读取数字输入
Scanner scanner = new Scanner(System.in);
System.out.print("输入年龄: ");
int age = scanner.nextInt(); // 自动转换类型
System.out.println("10年后年龄: " + (age + 10));
4. 使用技巧
- 包装流组合:
// 高效读取文本 BufferedReader br = new BufferedReader( new InputStreamReader(System.in, StandardCharsets.UTF_8) );
- Scanner 高级解析:
Scanner sc = new Scanner(System.in); double num = sc.nextDouble(); // 直接解析数字 LocalDate date = LocalDate.parse(sc.next()); // 解析日期
- 非阻塞读取尝试:
if (System.in.available() > 0) { int data = System.in.read(); }
5. 常见错误
错误 | 原因 | 解决方案 |
---|---|---|
乱码 | 未指定字符编码 | 明确设置 Charset 参数 |
InputMismatchException |
Scanner 类型不匹配 | 输入前校验 hasNextXXX() |
流未关闭 | 资源泄漏 (Scanner/BufferedReader) | 使用 try-with-resources |
换行符遗留 | nextInt() 后立即readLine() |
添加nextLine() 清空缓冲区 |
换行符错误示例:
Scanner sc = new Scanner(System.in);
System.out.print("输入数字: ");
int num = sc.nextInt(); // 读取数字但留换行符
System.out.print("输入文本: ");
String text = sc.nextLine(); // 读到空字符串!
修复:
int num = sc.nextInt();
sc.nextLine(); // 清除换行符
String text = sc.nextLine();
6. 注意事项
- 编码问题:跨平台时显式指定字符集
new InputStreamReader(System.in, "GBK") // 中文Windows环境
- 资源管理:避免关闭
System.in
(关闭后不可重新打开) - 阻塞特性:在 GUI 或网络应用中避免直接使用
- 缓冲区:输入需按回车才提交到程序
7. 最佳实践与性能优化
流重用:整个程序生命周期内保持单一
BufferedReader
实例大文件处理:避免用
System.in
处理大文件(设计用途是交互输入)性能对比: | 方式 | 读取10,000行耗时 | 内存占用 | 适用场景 | |----------------|------------------|----------|------------------| |
BufferedReader
| ~200ms | 低 | 文本行处理 | |Scanner
| ~500ms | 中 | 结构化数据解析 | | 直接read()
| ~150ms | 极低 | 二进制/低层操作 |安全输入:验证用户输入
Scanner sc = new Scanner(System.in); while (!sc.hasNextInt()) { System.out.println("请输入数字!"); sc.next(); // 丢弃非法输入 } int safeNum = sc.nextInt();
8. 总结
关键点 | 行动指南 |
---|---|
基础操作 | 优先用 BufferedReader + readLine() |
结构化输入 | 选择 Scanner 的 nextXxx() 方法 |
字符编码 | 显式指定 Charset (如 UTF-8) |
输入验证 | 配合 hasNextXxx() 做安全检查 |
资源管理 | 用 try-with-resources 管理包装流 |
性能敏感场景 | 直接操作字节(避免文本转换开销) |