1. 使用原生 Java

最推荐的方式:直接使用 InputStreamReader,简单粗暴,无需额外依赖。

InputStream 是字节流,而 Reader 是字符流,转换时必须指定字符编码(charset),否则可能踩坑乱码问题。如果不指定,会使用平台默认编码(如 Windows 的 GBK),跨平台时容易出问题。

@Test
public void givenUsingPlainJava_whenConvertingInputStreamIntoReader_thenCorrect() 
    throws IOException {
    InputStream initialStream = new ByteArrayInputStream("With Java".getBytes(StandardCharsets.UTF_8));
    
    Reader targetReader = new InputStreamReader(initialStream, StandardCharsets.UTF_8);

    // 使用后记得关闭
    targetReader.close();
}

📌 关键点

  • ✅ 推荐显式指定 UTF-8
  • InputStreamReaderReader 的子类,天然桥接字节流与字符流
  • ❌ 避免不指定编码的构造函数(已过时)

2. 使用 Guava

Guava 的方式略显绕路:先转成 byte[],再转成 String,最后包装成 Reader。虽然能用,但多了一次内存拷贝,性能不如原生 Java。

@Test
public void givenUsingGuava_whenConvertingInputStreamIntoReader_thenCorrect() 
    throws IOException {
    InputStream initialStream = ByteSource.wrap("With Guava".getBytes(StandardCharsets.UTF_8)).openStream();
    
    byte[] buffer = ByteStreams.toByteArray(initialStream);
    Reader targetReader = CharSource.wrap(new String(buffer, StandardCharsets.UTF_8)).openStream();

    targetReader.close();
}

📌 分析

  • ⚠️ 多次中间转换,浪费内存和 CPU
  • ✅ 代码可读性尚可,适合 Guava 重度使用者
  • ❌ 不推荐用于高频调用场景

小贴士:如果你项目已经在用 Guava,且只是偶尔转换,那也无所谓。但性能敏感场景请绕行


3. 使用 Apache Commons IO

Commons IO 的做法和 Guava 类似,也是通过 byte[] → String → Reader 的链路。它提供了 CharSequenceReader 来包装字符串。

@Test
public void givenUsingCommonsIO_whenConvertingInputStreamIntoReader_thenCorrect() 
    throws IOException {
    InputStream initialStream = IOUtils.toInputStream("With Commons IO", StandardCharsets.UTF_8);
    
    byte[] buffer = IOUtils.toByteArray(initialStream);
    Reader targetReader = new CharSequenceReader(new String(buffer, StandardCharsets.UTF_8));

    targetReader.close();
}

📌 注意点

  • IOUtils.toInputStream(String, Charset) 很方便
  • ⚠️ toByteArray() 会一次性加载整个流到内存,大文件有 OOM 风险
  • ❌ 同样存在多余对象创建,效率低于原生方案

总结对比

方式 是否需要依赖 推荐程度 适用场景
原生 Java ✅✅✅ 所有场景,首选方案
Guava 已引入 Guava 的项目
Commons IO 已引入 Commons IO 的旧项目

最终建议

优先使用 InputStreamReader(inputStream, StandardCharsets.UTF_8)简单、高效、安全
其他方式仅作为已有技术栈下的兼容选择,不要为了用而用。


原始标题:Java - InputStream to Reader | Baeldung