如何借助InputStream、DataInputStream通过System.in读取字符串
Java 基于System.in读取可变长度字符串的实现指南
核心问题根因拆解
- 现有代码中
dis.readChar()的设计逻辑不匹配控制台交互场景:该方法会固定读取2个字节拼接为Unicode字符,而日常控制台输入按照系统编码(UTF-8/GBK)传输单字节/多字节字符,二者逻辑错位会直接导致读取乱码 - 循环结构无有效退出条件:System.in作为控制台输入流默认处于阻塞状态,只有检测到EOF信号(Linux/macOS下按Ctrl+D,Windows下按Ctrl+Z)才会返回流末尾标记,无触发条件的无限循环会一直挂起等待输入
- 固定长度字节数组方案的固有缺陷:提前定义长度的字节数组无法适配长度不固定的输入,且
InputStream.read(byte[])本身不保证一次性读满整个数组,很容易出现内容读不全的问题
BufferedInputStream 核心运行逻辑
它是原生InputStream的包装实现,内置默认大小为8KB的内存缓冲区:底层触发读操作时,它不会直接向操作系统请求单字节数据,而是一次性拉取整块数据存入缓冲区;后续的读操作直接从内存缓冲区取数,大幅减少频繁单字节读取的IO开销。它本身不提供字节转字符串、行分隔识别的能力,仅做读性能优化。
可落地的实现方案
方案1:字符流按行读取(适配控制台输入的最优解)
将原生字节流转为字符流后套缓冲,直接按行读取,无需手动处理字节拼接、编码适配问题:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Exer10 { public static void main(String[] args) throws IOException { // 将System.in字节流转为指定编码的字符流,再套缓冲层提升读性能 BufferedReader br = new BufferedReader(new InputStreamReader(System.in, "UTF-8")); String lineContent; // readLine()读到换行符就返回当前行内容,读到EOF时返回null自动退出循环 while ((lineContent = br.readLine()) != null) { System.out.println("读取到的输入:" + lineContent); } } }
方案2:字节流体系实现(搭配BufferedInputStream)
如果必须沿用InputStream/DataInputStream的字节流体系,可通过动态集合收集读取到的字节,适配任意长度输入:
import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; public class Exer10 { public static void main(String[] args) throws IOException { InputStream is = System.in; // 套入BufferedInputStream优化单字节读取性能 BufferedInputStream bis = new BufferedInputStream(is); DataInputStream dis = new DataInputStream(bis); List<Byte> byteContainer = new ArrayList<>(); int currentByte; // 读到EOF标记(返回-1)时停止循环,支持任意长度输入 while ((currentByte = dis.read()) != -1) { byteContainer.add((byte) currentByte); } // 将收集到的字节按指定编码转为字符串 byte[] result = new byte[byteContainer.size()]; for (int i = 0; i < byteContainer.size(); i++) { result[i] = byteContainer.get(i); } String inputStr = new String(result, "UTF-8"); System.out.println("完整输入内容:" + inputStr); } }
常见踩坑提醒
- 不要将
DataInputStream作为通用字符串读取工具:它的设计目标是读写结构化二进制数据(如固定长度的int、long、自定义格式的UTF字符串),并不适配无固定结构的控制台交互输入 - 单独调用
readChar()无法正常读取控制台内容:2字节的固定读取逻辑和可变长的字符编码规则不匹配,很容易出现乱码 - 避免提前定义固定长度数组存储输入:固定长度数组既无法适配动态输入的长度,也容易因读不完整导致内容丢失,用动态集合收集字节或直接使用按行读取的字符流,才能从根本上解决问题
内容的提问来源于stack exchange,提问作者Miquel Àngel Cabot Prats
相关产品推荐
相关产品推荐

