ByteArrayInputStream和ByteArrayOutputStream是Java内存字节流,分别用于从字节数组读取和向内存写入数据,操作高效、无I/O开销,适用于临时缓存、数据转换及测试等场景。

ByteArrayInputStream 和 ByteArrayOutputStream 是 Java IO 中用于在内存中读写字节数组的流,不涉及磁盘或网络,适合临时缓存、数据转换、测试等场景。它们本质是把 byte[] 当作“源头”或“终点”,操作快、无 I/O 开销。
ByteArrayInputStream:从字节数组读取数据
它把一个已有的 byte[] 封装成输入流,支持标准 InputStream 的 read()、available()、mark()/reset() 等操作。
常见用法:
- 构造时传入 byte[];可选指定起始偏移和长度(避免复制)
- 适合配合 DataInputStream、ObjectInputStream、BufferedInputStream 等装饰器做解析
- 注意:它不会修改原数组,但多个线程并发读需自行同步(类本身非线程安全)
示例:
立即学习“Java免费学习笔记(深入)”;
byte[] data = "Hello, World".getBytes(StandardCharsets.UTF_8);
ByteArrayInputStream bis = new ByteArrayInputStream(data);
int b;
while ((b = bis.read()) != -1) {
System.out.print((char) b);
}
// 输出:Hello, World
ByteArrayOutputStream:向内存写入数据并获取结果数组
它内部维护一个可动态扩容的 byte[],所有 write() 操作都写入该缓冲区。调用 toByteArray() 或 toString() 可提取结果。
关键点:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 默认初始容量为 32 字节,自动扩容(类似 ArrayList),扩容策略是翻倍+新写入长度
- toByteArray() 返回的是当前内容的**副本**,后续写入不影响该数组
- toString() 默认用平台默认编码,建议显式传入 Charset(如 toString(StandardCharsets.UTF_8))
- close() 是空实现,可不调用;但 reset() 可清空缓冲区重用
示例:
立即学习“Java免费学习笔记(深入)”;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write("Java".getBytes(StandardCharsets.UTF_8));
bos.write(' ');
bos.write("IO".getBytes(StandardCharsets.UTF_8));
byte[] result = bos.toByteArray(); // 得到 "Java IO" 的字节数组
System.out.println(new String(result, StandardCharsets.UTF_8)); // 输出:Java IO
组合使用:内存中完成数据流转
二者常配对出现,比如模拟序列化/反序列化、压缩解压中间过程、HTTP 响应体构造等。
典型流程:
- 用 ByteArrayOutputStream 写入原始数据 → 获取字节数组
- 用 ByteArrayInputStream 包装该数组 → 交给需要 InputStream 的 API(如 XML 解析器、图片解码器)
示例(对象序列化到内存再反序列化):
// 序列化到内存
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(new Person("Alice", 30));
}
// 反序列化自内存
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
try (ObjectInputStream ois = new ObjectInputStream(bis)) {
Person p = (Person) ois.readObject(); // 成功还原
}
注意事项与替代方案
虽然方便,但要注意:
- 数据全驻留内存,大文件易引发 OOM;超 1MB 建议改用文件或流式处理
- Java 9+ 提供了更轻量的 java.util.Arrays#asList(byte[]) + InputStream#of(byte...)(静态工厂方法),适合简单一次性读取
- 若只需字符串操作,考虑 StringReader / StringWriter(字符流层面),避免编码转换开销
- Netty、Guava 等框架提供更高效的 ByteBuf / Bytes 类,适合高性能场景
不复杂但容易忽略细节,用对了能省去很多临时文件或 Socket 中转的麻烦。

















