1. 使用原生 Java 实现
在没有第三方库的情况下,我们可以用 JDK 自带的类完成 Reader
到 InputStream
的转换。核心思路是:先通过 Reader
读取字符数据到内存,再将字符串按指定编码转为字节数组,最后包装成 ByteArrayInputStream
。
✅ 优点:不依赖外部库
❌ 缺点:代码略长,需要手动管理缓冲区
示例代码如下:
@Test
public void givenUsingPlainJava_whenConvertingReaderIntoInputStream_thenCorrect()
throws IOException {
Reader initialReader = new StringReader("With Java");
char[] charBuffer = new char[8 * 1024];
StringBuilder builder = new StringBuilder();
int numCharsRead;
while ((numCharsRead = initialReader.read(charBuffer, 0, charBuffer.length)) != -1) {
builder.append(charBuffer, 0, numCharsRead);
}
InputStream targetStream = new ByteArrayInputStream(
builder.toString().getBytes(StandardCharsets.UTF_8));
initialReader.close();
targetStream.close();
}
⚠️ 注意:
- 使用了 8KB 的字符缓冲区,避免频繁 I/O 操作
- 显式指定
UTF-8
编码,防止因 JVM 默认编码不同导致乱码(踩坑点!) - 手动调用
close()
释放资源,Java 7+ 推荐使用 try-with-resources 更安全
2. 使用 Guava 实现
如果你的项目中已经引入了 Guava,那转换可以变得非常简单粗暴。
Guava 提供了 CharStreams.toString()
方法,能一键把 Reader
的内容读取为字符串,后续操作就和上面类似了。
✅ 优点:代码简洁,API 友好
❌ 缺点:需引入 Guava,对轻量级项目可能略重
@Test
public void givenUsingGuava_whenConvertingReaderIntoInputStream_thenCorrect()
throws IOException {
Reader initialReader = new StringReader("With Guava");
InputStream targetStream =
new ByteArrayInputStream(CharStreams.toString(initialReader)
.getBytes(Charsets.UTF_8));
initialReader.close();
targetStream.close();
}
📌 小贴士:Charsets.UTF_8
是 Guava 提供的常量,等价于 StandardCharsets.UTF_8
,但更早支持。
3. 使用 Apache Commons IO 实现
Apache Commons IO 是 Java 开发中非常常用的工具库,提供了多种便捷的 I/O 操作封装。
3.1 使用 ReaderInputStream
这是最直接的方式——ReaderInputStream
构造器直接接受 Reader
和 Charset
,内部自动处理字符到字节的转换。
@Test
public void givenUsingCommonsIOReaderInputStream_whenConvertingReaderIntoInputStream()
throws IOException {
Reader initialReader = new StringReader("With Commons IO");
InputStream targetStream = new ReaderInputStream(initialReader, Charsets.UTF_8);
initialReader.close();
targetStream.close();
}
⚠️ 注意:ReaderInputStream
是边读边转,不会一次性加载全部内容到内存,适合大文件场景。
3.2 使用 IOUtils
也可以通过 IOUtils.toString()
先转成字符串,再用 toInputStream()
转回字节流。
@Test
public void givenUsingCommonsIOUtils_whenConvertingReaderIntoInputStream()
throws IOException {
Reader initialReader = new StringReader("With Commons IO");
InputStream targetStream =
IOUtils.toInputStream(IOUtils.toString(initialReader), Charsets.UTF_8);
initialReader.close();
targetStream.close();
}
⚠️ 缺点:IOUtils.toString(reader)
会将整个内容加载进内存,不适合处理大文本,容易 OOM。
📌 推荐使用场景:
- 小数据量:两种方式都可
- 大数据量或流式处理:✅ 优先选
ReaderInputStream
4. 总结
方式 | 是否推荐 | 适用场景 |
---|---|---|
原生 Java | ⚠️ 一般 | 无第三方依赖,需手动控制缓冲 |
Guava | ✅ 推荐 | 已引入 Guava,代码简洁 |
Commons IO - ReaderInputStream | ✅ 强烈推荐 | 流式处理、大文件、生产环境首选 |
Commons IO - IOUtils | ⚠️ 谨慎 | 仅限小文本,避免内存溢出 |
📌 核心建议:
- ✅ 始终显式指定字符编码(如 UTF-8),不要依赖默认编码
- ✅ 优先使用
try-with-resources
管理资源,避免泄露 - ✅ 大文本处理务必选择流式方案(如
ReaderInputStream
)
完整示例代码已上传至 GitHub:https://github.com/baeldung/java-tutorials/tree/master/core-java-modules/core-java-io-conversions