ByteArrayInputStream 类详解
ByteArrayInputStream 类详解
ByteArrayInputStream
是 Java 中用于从字节数组读取数据的输入流,位于 java.io
包。它允许将内存中的字节数组当作输入流来读取,是处理内存数据的常用工具。
1. 核心特性
- 内存数据源:从字节数组(
byte[]
)读取数据 - 无需关闭:
close()
方法为空操作(无系统资源需要释放) - 线程不安全:多线程访问需外部同步
- 支持标记/重置:可重复读取数据(
mark()
和reset()
)
2. 类继承关系
3. 构造方法
构造方法 | 说明 |
---|---|
ByteArrayInputStream(byte[] buf) | 使用整个字节数组作为数据源 |
ByteArrayInputStream(byte[] buf, int offset, int length) | 使用数组的指定区间 |
4. 核心方法
(1)读取数据
方法 | 说明 |
---|---|
int read() | 读取单个字节(返回0-255,-1表示结束) |
int read(byte[] b, int off, int len) | 读取数据到字节数组 |
long skip(long n) | 跳过指定字节数 |
示例:
byte[] data = {72, 101, 108, 108, 111}; // "Hello"的ASCII码
ByteArrayInputStream bais = new ByteArrayInputStream(data);int byteRead;
while ((byteRead = bais.read()) != -1) {System.out.print((char) byteRead); // 输出: Hello
}
(2)流控制
方法 | 说明 |
---|---|
int available() | 返回剩余可读字节数 |
void mark(int readlimit) | 标记当前位置(readlimit 参数被忽略) |
void reset() | 重置到标记位置(默认是起始位置) |
boolean markSupported() | 始终返回 true (支持标记) |
标记/重置示例:
bais.mark(0); // 标记起始位置
System.out.print((char) bais.read()); // 读取'H'
bais.reset(); // 重置回起始位置
System.out.print((char) bais.read()); // 再次读取'H'
5. 使用场景
(1)内存数据处理
byte[] pdfData = generatePdf();
try (ByteArrayInputStream bais = new ByteArrayInputStream(pdfData);PDFParser parser = new PDFParser(bais)) {// 解析PDF数据
}
(2)单元测试模拟输入
// 模拟用户输入
String input = "test\n123\n";
ByteArrayInputStream testInput = new ByteArrayInputStream(input.getBytes());
System.setIn(testInput); // 重定向System.inScanner scanner = new Scanner(System.in);
System.out.println(scanner.nextLine()); // 输出: test
(3)与其他流配合
byte[] compressedData = getGzipData();
try (ByteArrayInputStream bais = new ByteArrayInputStream(compressedData);GZIPInputStream gzis = new GZIPInputStream(bais)) {// 解压数据
}
6. 性能优化
(1)批量读取
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = bais.read(buffer)) != -1) {process(buffer, 0, bytesRead);
}
(2)避免频繁创建
// 复用ByteArrayInputStream(调用reset()后重新读取)
bais.reset();
7. 与 ByteArrayOutputStream 对比
特性 | ByteArrayInputStream | ByteArrayOutputStream |
---|---|---|
方向 | 读取数据 | 写入数据 |
数据源 | 已有字节数组 | 动态增长缓冲区 |
关闭需求 | 非必需 | 非必需 |
典型用途 | 解析内存数据 | 收集输出数据 |
8. 常见问题
(1)数组越界
- 错误示例:
byte[] smallArray = new byte[10]; ByteArrayInputStream bais = new ByteArrayInputStream(smallArray, 5, 10); // 抛出IndexOutOfBoundsException
- 解决:确保
offset + length ≤ buf.length
(2)编码转换
- 正确方式:
byte[] utf8Bytes = "中文".getBytes("UTF-8"); ByteArrayInputStream bais = new ByteArrayInputStream(utf8Bytes); String text = new String(toByteArray(bais), "UTF-8");
9. 实战案例
(1)Base64 解码
String base64 = "SGVsbG8="; // "Hello"的Base64编码
byte[] decoded = Base64.getDecoder().decode(base64);
ByteArrayInputStream bais = new ByteArrayInputStream(decoded);
// 使用解码后的数据...
(2)图像处理
byte[] imageData = getImageBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
BufferedImage image = ImageIO.read(bais);
10. 总结
- 适用场景:内存数据解析、测试数据模拟、与其他流配合
- 优势:无需物理I/O,轻量高效
- 注意:大数据量需考虑内存限制
扩展练习:
- 实现一个方法,将
ByteArrayInputStream
内容复制到ByteArrayOutputStream
- 结合
DataInputStream
读取结构化二进制数据