ByteArrayOutputStream 继承自 OutputStream 。
OutputStream 的源码分析见:http://blog.csdn.net/yx0628/article/details/79370689
同时可以参考 ByteArrayInputStream 的源码:http://blog.csdn.net/yx0628/article/details/79346595
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException 。
属性
// 缓冲字节数组,数据写入这里
protected byte buf[];
// 字节数组中的有效字节个数
protected int count;
// 数组最大容量值(和ArrayList的数组最大值同样道理)
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
构造函数
// 创建一个新的字节数组输出流
public ByteArrayOutputStream() {
this(32);
}
// 根据给定的缓冲字节数组大小来创建字节数组输出流
public ByteArrayOutputStream(int size) {
if (size < 0) {
throw new IllegalArgumentException("Negative initial size: "
+ size);
}
buf = new byte[size];
}
方法
容量扩张
private void ensureCapacity(int minCapacity) {
// 如果需要的最小容量大于数组的容量,那么调用grow函数来扩展
// 否则,不需要改变这个数组的大小
if (minCapacity - buf.length > 0)
grow(minCapacity);
}
// 扩张容量
private void grow(int minCapacity) {
// 保存当前的数组大小
int oldCapacity = buf.length;
// 新的大小将旧大小扩张二倍
int newCapacity = oldCapacity << 1;
// 此时判断新容量和所需容量,如果新容量还不满足要求,使用所需容量作为新容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 然后比较新容量和最大容量,如果新容量大于最大容量,调用hugeCapacity方法
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 将旧数组中所有字节拷贝到新容量大小的新数组中,这个新数组作为新的缓冲字节数组
buf = Arrays.copyOf(buf, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
// 如所需容量大于最大容量,那么就使用最大整数,否则就使用最大容量即可
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
write(int b)
// 同步方法,写入一个字节
public synchronized void write(int b) {
// 调用ensureCapacity函数确保count位置有空间可以写入
// count由于是已存在有效字节的个数,比如count为10,代表数组中0-9这10个位置有字节
// 如果数组容量就是10,那么count下标即10的下标是越界的,所以要进行判断
// 这里要么有空间直接能写入,要么扩张大小后写入字节
ensureCapacity(count + 1);
// 将字节写入count下标处
buf[count] = (byte) b;
// 有效字节数count加1
count += 1;
}
write(byte b[], int off, int len)
// 同步方法,从给定的字节数组b中从下标off开始将len个字节写入输出流
public synchronized void write(byte b[], int off, int len) {
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) - b.length > 0)) {
// 偏移量off及个数len应该满足的条件,否则抛出范围异常
throw new IndexOutOfBoundsException();
}
// 确保空间是否需要增长len的长度
ensureCapacity(count + len);
// 数组拷贝,b数组off下标开始拷贝到buf数组count下标处,共len个字节
System.arraycopy(b, off, buf, count, len);
// 元素个数count增加len个
count += len;
}
writeTo(OutputStream out)
将此 byte 数组输出流的全部内容写入到指定的输出流。
// 这里是将当前字节数组流的字节数组的所有字节,写入到目标输出流中
public synchronized void writeTo(OutputStream out) throws IOException {
out.write(buf, 0, count);
}
reset()
public synchronized void reset() {
// 将count置为0,代表字节数组中的字节都要丢弃
count = 0;
}
byte toByteArray()[]
public synchronized byte toByteArray()[] {
// 创建一个新分配的byte数组
// 其大小是此输出流的当前大小,并且缓冲区的有效内容已复制到该数组中。
return Arrays.copyOf(buf, count);
}
size()
public synchronized int size() {
// 返回字节数组中有效字节的个数
return count;
}
toString
// 使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。
public synchronized String toString() {
return new String(buf, 0, count);
}
// 使用指定的字符集,通过解码字节将缓冲区内容转换为字符串。
public synchronized String toString(String charsetName)
throws UnsupportedEncodingException
{
return new String(buf, 0, count, charsetName);
}
close()
关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException 。
// close方法未实现具体行为
public void close() throws IOException {
}