You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何借助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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 11:24:02