导读
上篇文章介绍了两种常用的文件输入输出流:
https://blog.csdn.net/qiaojialin/article/details/81031422
其中向文件中写入的数据都是预先定义好的字节数组 byte[] ,本文介绍另一种在内存中维护字节数组更常用的方式:内存数组输入输出流。
ByteArrayOutputStream
内存数组流,就是和内存中的数组相关的一个流,可以将字节数组写到输出流中,也可以将字节数组从输入流中读出来,不涉及磁盘。内存数组输出流可以看成一个可自动扩容的 byte 数组,可以往里写字节。
默认初始化 32 个字节的大小。最大容量是 2^31-9 个字节(2G)。只要数据不超过2G,都可以往里写。每次写数据之前,会先计算需要的容量大小,如果需要扩容,扩大到 max{原来的两倍,需要的容量大小}
此外,还可以将 ByteArrayOutputStream 中的字节数组拿出来,拿出来的只是真实存在的数据量。
//为了验证扩容方式,把其内部缓冲区拿出来
class MyByteArrayOutputStream extends ByteArrayOutputStream {
public byte[] getBuf() {
return super.buf;
}
}
private static void outputStreamTest() throws IOException {
// 默认缓冲区大小 32 字节
MyByteArrayOutputStream out = new MyByteArrayOutputStream();
// 写入 32 个字节,此时
for(int i = 0; i < 32; i++) {
out.write(1);
}
System.out.println("当前缓冲区长度:" + out.getBuf().length + " 当前数据长度:" + out.size());
// 写入 1 个字节,使所需容量为 33 个字节,大于原来 32 字节的容量
out.write(2);
System.out.println("当前缓冲区长度:" + out.getBuf().length + " 当前数据长度:" + out.size() + " 扩大到原来的两倍了");
// 取出数据
byte[] ret = out.toByteArray();
print(ret);
// 写入新数据,使其空间正好比原空间的 2 倍大 3 个字节
out.write(new byte[out.getBuf().length*2-out.size()+3]);
System.out.println("当前缓冲区长度:" + out.getBuf().length + " 当前数据长度:" + out.size() + " 扩大到需要的容量大小了");
}
输出:
当前缓冲区长度:32 当前数据长度:32
当前缓冲区长度:64 当前数据长度:33 扩大到原来的两倍了
长度: 33 ,内容:111111111111111111111111111111112
当前缓冲区长度:131 当前数据长度:131 扩大到需要的容量大小了
ByteArrayInputStream
这个输入流就是把一个字节数组 byte[] 包装了一下,使其具有流的属性,可顺序读下去。还可标记跳回来继续读。
private static void inputStreamTest() throws IOException {
byte[] b1 = new byte[]{1,2,3,4};
ByteArrayInputStream input = new ByteArrayInputStream(b1);
System.out.println("剩余字节数: "+input.available());
byte[] b2 = new byte[2];
input.read(b2);
print(b2);
System.out.println("剩余字节数: " + input.available());
input.read(b2);
print(b2);
System.out.println("剩余字节数: " + input.available() + " 没得读了");
b2 = new byte[2];
input.read(b2);
print(b2);
}
private static void print(byte[] array) {
System.out.print("长度: " + array.length + " ,内容:");
for (byte b : array) {
System.out.print(b);
}
System.out.println();
}
输出:
剩余字节数: 4
长度: 2 ,内容:12
剩余字节数: 2
长度: 2 ,内容:34
剩余字节数: 0 没得读了
长度: 2 ,内容:00
为什么要用 ByteArrayInputStream 而不直接操作 byte 数组?有以下几种情况:
(1)其他接口需要一个 InputStream,而你只有一个 byte[],这时候必须包装一下。
(2)希望以流的方式操作字节数组。
如果其他地方只需要一个 byte[],就没必要包装了,直接传 byte[] 就好了。
这两个流都是对内存中的数据进行操作,在需要动态维护一个字节数组时,可以使用 ByteArrayOutputStream,这个变量通常叫 baos 。另外,此次代码和上次代码都放在 github 上了,可以点阅读原文,下边这个也是:
https://github.com/qiaojialin/Java-IO-Learning
欢迎关注个人公众号:数据库漫游指南