ByteArrayOutputStream是字节数组输出流,在内存中创建了一个字节数组,所有发送到输出流的数据都会保存到该字节数组的缓冲区中。当数据写入缓冲区时, 缓冲区大小会按需增长。可以使用toByteArray和toString取出数据。
public class ByteArrayOutputStreamDemo {
public static void main(String[] args) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream("D:\\jdk_s_d\\out.txt");
int len;
while ((len = fis.read()) != -1) {
// 把读取到的数据逐个写到ByteArrayOutputStream中
bos.write(len);
}
byte[] array = bos.toByteArray();
// 指定解码的字符集
System.out.println(new String(array, "utf-8"));
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
源码(1.8):
public class ByteArrayOutputStream extends OutputStream {
/**
* 保存字节数组输出流数据的字节数组
*/
protected byte buf[];
/**
* 流中有效字节数
*/
protected int count;
/**
* 创建一个默认为32字节缓冲大小的ByteArrayOutputStream.
*/
public ByteArrayOutputStream() {
this(32);
}
/**
* 创建一个指定大小的ByteArrayOutputStream.
*/
public ByteArrayOutputStream(int size) {
if (size < 0) {
throw new IllegalArgumentException("Negative initial size: "
+ size);
}
buf = new byte[size];
}
/**
* 必要时增加容量,
* 以确保它至少可以容纳minCapacity个字节.
*/
private void ensureCapacity(int minCapacity) {
//如果buf的长度小于minCapacity,则需要扩容
if (minCapacity - buf.length > 0)
grow(minCapacity);
}
/**
* 要分配的数组的最大大小。
* 一些VM在数组中保留一些头字节。
* 尝试分配较大的数组可能
* 会导致OutOfMemory错误:请求的数组大小超过了VM限制
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 增加容量
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = buf.length;
// <<:左移运算符,oldCapacity << 1,相当于oldCapacity乘以2
int newCapacity = oldCapacity << 1;
//扩容2倍之后仍然小于minCapacity,则newCapacity = minCapacity;
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新的容量大于容量的最大值MAX_ARRAY_SIZE,
//则扩容至最大值Integer.MAX_VALUE
//否则扩容至Integer.MAX_VALUE - 8
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//把原buf的内容拷贝到扩容后的数组,并赋值给buf
buf = Arrays.copyOf(buf, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
/**
* 将指定的字节写入此字节数组输出流
*/
public synchronized void write(int b) {
ensureCapacity(count + 1);
buf[count] = (byte) b;
count += 1;
}
/**
* 将从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)) {
throw new IndexOutOfBoundsException();
}
ensureCapacity(count + len);
System.arraycopy(b, off, buf, count, len);
count += len;
}
/**
* 将此字节数组输出流的完整内容写入指定的输出流参数,
* 就像使用out.write(buf,0,count)调用输出流的write方法一样。
*/
public synchronized void writeTo(OutputStream out) throws IOException {
out.write(buf, 0, count);
}
/**
* 将此字节数组输出流的count字段重置为零,
* 以便丢弃输出流中当前累积的所有输出。
* 输出流可以再次使用,重用已分配的缓冲区空间
*/
public synchronized void reset() {
count = 0;
}
/**
* 创建新分配的字节数组。
* 它的大小是此输出流的当前大小,
* 缓冲区的有效内容已复制到其中
*/
public synchronized byte toByteArray()[] {
return Arrays.copyOf(buf, count);
}
/**
* 返回buf大小
*/
public synchronized int size() {
return count;
}
/**
*使用平台的默认字符集
*将缓冲区的内容转换为字符串解码字节。
*新字符串的长度是字符集的函数,
*因此可能不等于缓冲区的大小.
*/
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);
}
/**
* 已弃用
*/
@Deprecated
public synchronized String toString(int hibyte) {
return new String(buf, hibyte, 0, count);
}
/**
* 关闭,虚拟机自动回收
*/
public void close() throws IOException {
}
}
更多精彩内容,请关注微信公众号: