System.in
详解
System.in
是 Java 提供的标准输入流(InputStream
类型),默认关联键盘输入,通常用于从控制台读取用户输入。由于它是字节流(InputStream
),直接使用较麻烦,一般会配合 Scanner
或 BufferedReader
进行字符读取。
1.标准输入流是用来接收用户在控制台上的输入的。(普通的输入流,是获得文件或网络中的数据)
2.标准输入流不需要关闭(它是一个系统级的全局的流,JVM负责最后的关闭)
3.也可以使用BufferedReader对标准输入流进行包装。这样可以方便的接收用户在控制台上的输入。(这种方式太麻烦了,因此JDK中提供了更好用的Scanner)
4.当然,你也可以修改输入流的方向(System.setIn())。让其指向文件。
1. 核心知识点
(1)System.in
的本质
-
类型:
InputStream
(字节流,不是字符流)。 -
默认行为:阻塞式读取(程序会等待用户输入)。
-
使用场景:控制台输入、重定向输入(如
java Main < input.txt
)。
(2)直接读取字节(原始方法)
java
try { int byteData = System.in.read(); // 读取1个字节(返回ASCII码) System.out.println("输入的内容:" + (char) byteData); } catch (IOException e) { e.printStackTrace(); }
-
缺点:只能读单个字节,中文会乱码(需用字符流处理)。
2. 常用封装方式
由于 System.in
是字节流,通常需要转换为字符流方便使用:
(1)配合 Scanner
(最常用)
java
Scanner scanner = new Scanner(System.in); System.out.print("请输入姓名:"); String name = scanner.nextLine(); // 读取一行 System.out.println("你好," + name); scanner.close();
优点:
-
支持按行、按单词、按数据类型(
nextInt()
、nextDouble()
)读取。 -
自动处理编码问题(默认使用系统字符集)。
(2)配合 BufferedReader
(高效读取)
java
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); System.out.print("请输入年龄:"); String ageStr = reader.readLine(); // 读取一行 int age = Integer.parseInt(ageStr); System.out.println("年龄:" + age); reader.close();
优点:
-
适合大文本输入(缓冲机制提升性能)。
-
显式指定编码(如
UTF-8
):java
new InputStreamReader(System.in, StandardCharsets.UTF_8)
(3)对比 Scanner
vs BufferedReader
特性 | Scanner | BufferedReader |
---|---|---|
读取方式 | 按行、单词、数据类型 | 仅按行(readLine() ) |
性能 | 较慢(正则解析开销) | 更快(纯缓冲读取) |
适用场景 | 交互式输入(如控制台菜单) | 大文件或连续文本输入 |
3. 关键问题与解决方案
(1)中文乱码问题
-
原因:
System.in
是字节流,默认使用系统编码(如 Windows 的GBK
),如果控制台编码不一致(如 IDEA 默认UTF-8
),会导致乱码。 -
解决:强制指定编码:
java
BufferedReader reader = new BufferedReader( new InputStreamReader(System.in, StandardCharsets.UTF_8) );
(2)输入阻塞与超时
-
System.in.read()
会一直等待输入,若需超时控制,需用线程或NIO
(如System.in.available()
检查是否有数据)。
(3)关闭问题
-
不要关闭
System.in
!否则后续代码无法再使用控制台输入。 -
只需关闭封装流(如
Scanner
或BufferedReader
):java
scanner.close(); // 会同时关闭底层 System.in(慎用!) // 推荐:仅关闭包装流 BufferedReader reader = ...; reader.close(); // 不影响 System.in
4. 记忆技巧
(1)流程图:读取控制台输入
System.in (字节流) ↓ InputStreamReader (字节→字符,可指定编码) ↓ BufferedReader/Scanner (高效或灵活读取)
(2)口诀
"系统输入用
in
,
字节流转字符才顺,
Scanner
方便小输入,
BufferedReader
大文本稳!"
5. 面试常见问题
-
System.in
是什么类型?它的缺点是什么?-
类型:
InputStream
(字节流)。 -
缺点:直接使用需处理字节转换,不支持按行/数据类型读取。
-
-
如何避免
Scanner
关闭后导致System.in
不可用?-
避免直接调用
scanner.close()
,或改用BufferedReader
。
-
-
如何用
System.in
读取中文?-
通过
InputStreamReader
指定编码(如UTF-8
)。
-
6. 实战应用
-
控制台交互程序(如命令行工具):
java
Scanner scanner = new Scanner(System.in); while (true) { System.out.print("> "); String command = scanner.nextLine(); if ("exit".equalsIgnoreCase(command)) break; System.out.println("执行命令:" + command); }
-
重定向输入测试:
sh
java Main < input.txt # 从文件读取输入
总结
-
System.in
是 Java 标准输入流,需配合Scanner
或BufferedReader
使用。 -
优先用
Scanner
:简单交互(如读取数字、单词)。 -
优先用
BufferedReader
:高性能读取(如大文本或需要编码控制)。 -
注意:不要关闭
System.in
,避免编码乱码!
练习建议:
-
写一个控制台计算器(读取用户输入的数字和运算符)。
-
比较
Scanner
和BufferedReader
读取大文件的速度差异。