(二)ByteArrayInputStream与ByteArrayOutputStream

来源:互联网 发布:java实现双向链表 编辑:程序博客网 时间:2024/05/29 07:07

ByteArrayInputStream总结:

  1. ByteArrayInputStream就是提供一个对字节数组的读接口,所以构造函数需要一个字节数组作为数据源。所有的读操作都是对读该数组。
  2. 因为需要对pos/count进行操作,为了保证多线程下的有效性,所有的read方法都进行了同步。

ByteArrayOutputStream总结:

  1. ByteArrayOutputStream提高一个对字节数组的写操作,内部将写入的数据放在一个字节数组中。
  2. 内部数组默认初始长度为32,也可以通过构造函数指定大小。
  3. writeTo(OutputStream out)可以将缓存的数据保存到真正的目的源中
  4. 当内部数组容量不足时,会自动扩容

使用场景:

在我的有限经验中很少用到,以下是我的一些理解。
1. 可以存储其他输入流数据,在关闭流之后,仍然可以操作数据(可以释放I/O资源)。
2. 需要对字符串进行字节操作时

ByteArrayInputStream源码

package java.io;public class ByteArrayInputStream extends InputStream {    //输入源    protected byte buf[];    //下一个读取的数组下标        protected int pos;    //记录要恢复的下标    protected int mark = 0;    //输入源长度    protected int count;    //这两个构造函数都需要传入一个字节数组,而这个数组就输入源,相关read()方法都是从这个数组读取数据    public ByteArrayInputStream(byte buf[]) {        this.buf = buf;        this.pos = 0;        this.count = buf.length;    }    public ByteArrayInputStream(byte buf[], int offset, int length) {        this.buf = buf;        this.pos = offset;        this.count = Math.min(offset + length, buf.length);        this.mark = offset;    }    //byte转int,需要&0xff,为什么不返回byte呢?这个后面另讲    public synchronized int read() {        return (pos < count) ? (buf[pos++] & 0xff) : -1;    }    public synchronized int read(byte b[], int off, int len) {        //参数有效性检查        if (b == null) {            throw new NullPointerException();        } else if (off < 0 || len < 0 || len > b.length - off) {            throw new IndexOutOfBoundsException();        }        //数据全部读完返回-1        if (pos >= count) {            return -1;        }        //计算最多可读字节长度        int avail = count - pos;        if (len > avail) {            len = avail;        }        if (len <= 0) {            return 0;        }        System.arraycopy(buf, pos, b, off, len);        pos += len;        return len;    }    //跳过n个字节,在缓存数组长度范围内偏移指针即可    public synchronized long skip(long n) {        long k = count - pos;        if (n < k) {            k = n < 0 ? 0 : n;        }        pos += k;        return k;    }    //未读长度    public synchronized int available() {        return count - pos;    }    //是否支持复位    public boolean markSupported() {        return true;    }    //标记和复位也很简单,因为都是对数组操作    public void mark(int readAheadLimit) {        mark = pos;    }    public synchronized void reset() {        pos = mark;    }    //没有涉及底层I/O,不需要关闭    public void close() throws IOException {    }}

ByteArrayOutputStream类源码

package java.io;import java.util.Arrays;public class ByteArrayOutputStream extends OutputStream {   //输出源    protected byte buf[];    protected int count;    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) {        // overflow-conscious code        if (minCapacity - buf.length > 0)            grow(minCapacity);    }    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;    private void grow(int minCapacity) {        // overflow-conscious code        int oldCapacity = buf.length;        int newCapacity = oldCapacity << 1;        if (newCapacity - minCapacity < 0)            newCapacity = minCapacity;        if (newCapacity - MAX_ARRAY_SIZE > 0)            newCapacity = hugeCapacity(minCapacity);        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;    }    //这里write()方法最终都是输入到一个字节数组中,数组的长度是根据内容长度自动增长的    public synchronized void write(int b) {        ensureCapacity(count + 1);        buf[count] = (byte) b;        count += 1;    }    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;    }    public synchronized void writeTo(OutputStream out) throws IOException {        out.write(buf, 0, count);    }    public synchronized void reset() {        count = 0;    }    public synchronized byte toByteArray()[] {        return Arrays.copyOf(buf, count);    }    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 {    }}

ByteArrayOutputStream缓存数组自动扩容方法

    //判断是否需要扩容,每次调用write方法都会调用该方法进行判断    //minCapacity:最小容量,一般是count+len(len为写入长度)    private void ensureCapacity(int minCapacity) {        // overflow-conscious code        if (minCapacity - buf.length > 0)            grow(minCapacity);    }    //数组最大长度。为什么要Integer.MAX_VALUE - 8?    //部分虚拟机需要在数组中保存相关信息,占用一定空间    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;    //真正的扩容函数    private void grow(int minCapacity) {        // overflow-conscious code        int oldCapacity = buf.length;        int newCapacity = oldCapacity << 1;//左移1位就是2倍大小        if (newCapacity - minCapacity < 0)//取最小,不要浪费空间            newCapacity = minCapacity;        if (newCapacity - MAX_ARRAY_SIZE > 0)//超过规定大小了怎么办            newCapacity = hugeCapacity(minCapacity);        buf = Arrays.copyOf(buf, newCapacity);    }    private static int hugeCapacity(int minCapacity) {        if (minCapacity < 0) // overflow//count+len溢出了,超过Integer.MAX_VALUE            throw new OutOfMemoryError();            //实在没办法了,最多就给Integer.MAX_VALUE,什么头部信息的不管了        return (minCapacity > MAX_ARRAY_SIZE) ?            Integer.MAX_VALUE :            MAX_ARRAY_SIZE;    }




参考文章

Java io系列

阅读全文
0 0