ByteArrayInputStream and ByteArrayOutputStream 源码学习笔记

之前看过一篇文章,说是输入流主要从文件file,字节数组,StringBuffer,其他线程,已经被序列化的对象读取数据,发现功能不是特别完善,为减少类的创建,使用装饰者模式,使用FilterInputStream去派生装饰者类,例如BufferedInputStream,提供缓冲功能。看ByteArrayInputStream和ByteArrayOutputStream源码时,给我感觉是完全没有流的概念,就是提供操作字节数组的类,ByteArrayOutStream可以将数据写入到流中,却是借他人之手,因为它本身不具有这个能力,所以它的close方法是空的,不起任何作用。
先看下ByteArrayInputStream:

它是支持mark的

public boolean markSupported() {
        return true;
    }
    }

定义:

public class ByteArrayInputStream extends InputStream

主要数据成员:和BufferedInputStream不同的是它没有marklimit去接收mark参数,看mark源码时也确实能够看出参数被抛弃了。

protected byte buf[];
protected int pos;
protected int mark = 0;
protected int count;

构造器:很有意思的是buf只要直接引用(现成的数据)就行,使用length确定count大小,最大为buf.length。

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

read(逻辑很简单,不做介绍,下面也一样):

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();
        }

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

skip:

public synchronized long skip(long n) {
        long k = count - pos;
        if (n < k) {
            k = n < 0 ? 0 : n;
        }

        pos += k;
        return k;
    }

available:

public synchronized int available() {
        return count - pos;
    }

mark:

public void mark(int readAheadLimit) {
        mark = pos;
    }

reset:

public synchronized void reset() {
        pos = mark;
    }

close:

 public void close() throws IOException {
    }

以上贴出的源码合起来就是这个类的总源码数,它没有任何的native方法,所以它也没有交互的能力。写这篇博客的最主要的原因是想记录下ByteArrayOutputStream的使用。

ByteArrayOutputStream定义:

public class ByteArrayOutputStream extends OutputStream

主要数据成员:

protected byte buf[];
protected int count;

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];
    }    

write:前两个write将数据存入buf中,第3个是将buf写入到流中
out.write(buf, 0, count),觉得这个写入很特别,配合reset方法看,count充当pos的角色

 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);
    }  

扩容方法:和ArrayList有点像

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

reset:丢掉buf中的数据,虽然数据还在buf中,但是这部分数据不会写入到流中。

 public synchronized void reset() {
        count = 0;
    }

toByteArray:

 public synchronized byte toByteArray()[] {
        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:

 public void close() throws IOException {
    }

除了有一个废弃的toString(int hibyte)没有贴出来,这个类的所有源码都已经被贴出来了,可以看到它也没有native方法,需要借助一个输出流将buf写入到流中。
这大概是我见过最简单的源码了,ByteArrayOutputStream源码中count是用的最巧妙的,可以说它就是buf有用数据的上限。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值