1. 使用原生 Java 实现
最直接的方式是通过中间 String
对象进行转换。虽然简单粗暴,但在某些场景下仍很实用 ✅
核心思路是:
- 以字符数组为缓冲区,分块读取
Reader
内容到StringBuilder
- 最后将字符串通过
.getBytes()
转为字节数组 - ⚠️ 注意编码问题!默认使用平台编码,生产环境建议显式指定(如 UTF-8)
@Test
public void givenUsingPlainJava_whenConvertingReaderIntoByteArray_thenCorrect()
throws IOException {
Reader initialReader = new StringReader("With Java");
char[] charArray = new char[8 * 1024];
StringBuilder builder = new StringBuilder();
int numCharsRead;
while ((numCharsRead = initialReader.read(charArray, 0, charArray.length)) != -1) {
builder.append(charArray, 0, numCharsRead);
}
byte[] targetArray = builder.toString().getBytes(StandardCharsets.UTF_8); // 推荐指定编码
initialReader.close();
}
📌 踩坑提醒:不要一次读一个字符,性能极差 ❌。一定要用缓冲数组批量读取。
2. 使用 Guava 工具库
如果你项目中已经引入了 Guava,那可以更优雅地处理 IO 操作 ✅
CharStreams.toString()
是个神器,能自动完成流的读取和关闭(配合 try-with-resources 更佳),代码瞬间清爽不少:
@Test
public void givenUsingGuava_whenConvertingReaderIntoByteArray_thenCorrect()
throws IOException {
Reader initialReader = CharSource.wrap("With Google Guava").openStream();
byte[] targetArray = CharStreams.toString(initialReader).getBytes(StandardCharsets.UTF_8);
initialReader.close();
}
💡 小技巧:实际使用中建议包裹在 try-with-resources 中,避免资源泄漏:
try (Reader reader = CharSource.wrap("data").openStream()) { return CharStreams.toString(reader).getBytes(UTF_8); }
3. 使用 Apache Commons IO
最推荐的方式 —— Commons IO 提供了开箱即用的直接转换方法 ✅✅✅
IOUtils.toByteArray(Reader)
内部会自动处理缓冲和编码,默认使用 UTF-8,简洁又安全:
@Test
public void givenUsingCommonsIO_whenConvertingReaderIntoByteArray_thenCorrect()
throws IOException {
StringReader initialReader = new StringReader("With Commons IO");
byte[] targetArray = IOUtils.toByteArray(initialReader, StandardCharsets.UTF_8);
initialReader.close();
}
🔥 重点推荐这个方案,原因如下:
- 方法语义清晰,一行搞定
- 底层优化良好,性能优于手动拼接字符串
- 支持编码参数,避免乱码踩坑
- 属于主流 IO 工具库,维护稳定,兼容性好
📌 总结建议:
方式 | 是否推荐 | 适用场景 |
---|---|---|
原生 Java | ❌ | 学习原理、无法引入第三方库时兜底 |
Guava | ✅ | 项目已使用 Guava,且偏好函数式风格 |
Commons IO | ✅✅✅ | 通用首选,简单高效,专为这类问题而生 |
生产环境优先选 Commons IO,省事还靠谱 💯