InputStreamReader 本质是将 System.in 字节流转为字符流,需显式指定 UTF-8 编码、配合 BufferedReader 使用 readLine() 按行读取,并用 try-with-resources 确保资源关闭,避免乱码与阻塞问题。

用 InputStreamReader 读取 System.in,本质是把字节流(System.in)转换为字符流,方便按字符或行读取。关键在于正确处理编码、缓冲和关闭逻辑。
基础用法:包装 System.in 并读取单个字符
InputStreamReader 是 Reader 的子类,需传入 System.in 构造。默认使用平台默认编码,也可显式指定(推荐):
- 调用
read()返回一个int(0–65535),-1 表示流结束 - 需强制转为
char才能打印或使用 - 注意:该方法会阻塞,直到有输入或流关闭
InputStreamReader reader = new InputStreamReader(System.in, "UTF-8");
int ch;
while ((ch = reader.read()) != -1) {
System.out.print((char) ch);
}
reader.close();
推荐方式:配合 BufferedReader 按行读取
InputStreamReader 本身不带缓冲,也不支持 readLine()。实际开发中应套一层 BufferedReader 提升效率并简化操作:
-
BufferedReader的readLine()返回String,更符合日常需求 - 仍需指定编码,避免中文乱码(尤其 Windows 默认 GBK,Linux/macOS 默认 UTF-8)
- 建议用 try-with-resources 自动关闭资源
try (InputStreamReader isr = new InputStreamReader(System.in, "UTF-8");
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
if ("quit".equalsIgnoreCase(line)) break;
System.out.println("你输入了:" + line);
}
} catch (IOException e) {
e.printStackTrace();
}
常见问题与注意事项
直接用 InputStreamReader 读标准输入容易踩坑,需留意:
-
编码不一致导致乱码:务必显式传入
"UTF-8",不要依赖平台默认 -
未关闭资源:虽然
System.in关闭无实际影响,但养成 close 习惯可避免静态分析警告 -
read() 返回值是 int 不是 char:直接赋给
char变量会丢失 -1 判断能力,必须先判断再转 -
控制台输入的换行符差异:Windows 是
\r\n,Linux/macOS 是\n;readLine()会自动去除,无需手动 trim
替代方案对比:Scanner vs InputStreamReader + BufferedReader
如果只是读字符串、数字等简单类型,Scanner 更简洁:
-
Scanner sc = new Scanner(System.in, "UTF-8")同样支持编码设置 -
sc.nextLine()、sc.nextInt()等方法开箱即用 - 但
Scanner在混合读取(如先 nextInt 再 nextLine)时易因换行符残留出错,此时BufferedReader更可控
所以,纯文本逐行处理优先选 InputStreamReader + BufferedReader;需要解析结构化输入(如数字、单词)可考虑 Scanner,但要注意其行为边界。










