JDK源码(六):ByteArrayOutputStream

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 {
    }

}

更多精彩内容,请关注微信公众号:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐楠_01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值