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. 使用技巧

  1. 包装流组合
    // 高效读取文本
    BufferedReader br = new BufferedReader(
        new InputStreamReader(System.in, StandardCharsets.UTF_8)
    );
    
  2. Scanner 高级解析
    Scanner sc = new Scanner(System.in);
    double num = sc.nextDouble();  // 直接解析数字
    LocalDate date = LocalDate.parse(sc.next());  // 解析日期
    
  3. 非阻塞读取尝试
    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. 注意事项

  1. 编码问题:跨平台时显式指定字符集
    new InputStreamReader(System.in, "GBK") // 中文Windows环境
    
  2. 资源管理:避免关闭 System.in(关闭后不可重新打开)
  3. 阻塞特性:在 GUI 或网络应用中避免直接使用
  4. 缓冲区:输入需按回车才提交到程序

7. 最佳实践与性能优化

  1. 流重用:整个程序生命周期内保持单一 BufferedReader 实例

  2. 大文件处理:避免用 System.in 处理大文件(设计用途是交互输入)

  3. 性能对比: | 方式 | 读取10,000行耗时 | 内存占用 | 适用场景 | |----------------|------------------|----------|------------------| | BufferedReader | ~200ms | 低 | 文本行处理 | | Scanner | ~500ms | 中 | 结构化数据解析 | | 直接read() | ~150ms | 极低 | 二进制/低层操作 |

  4. 安全输入:验证用户输入

    Scanner sc = new Scanner(System.in);
    while (!sc.hasNextInt()) {
        System.out.println("请输入数字!");
        sc.next(); // 丢弃非法输入
    }
    int safeNum = sc.nextInt();
    

8. 总结

关键点 行动指南
基础操作 优先用 BufferedReader + readLine()
结构化输入 选择 ScannernextXxx() 方法
字符编码 显式指定 Charset (如 UTF-8)
输入验证 配合 hasNextXxx() 做安全检查
资源管理 用 try-with-resources 管理包装流
性能敏感场景 直接操作字节(避免文本转换开销)