Java8 I/O源码-BufferedInputStream与BufferedOutputStream

前面已经学习了FilterInputStream与FilterOutputStream。文章中到了FilterInputStream与FilterOutputStream的子类可进一步重写父类方法中的一些方法,来提供装饰功能。今天就来介绍下它们子类中的BufferedInputStream与BufferedOutputStream。

BufferedInputStream是缓冲输入流,作用是为另一个输入流添加一些功能,比如缓冲输入功能以及支持mark和reset方法的能力。在创建BufferedInputStream时,会在内存中创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流一次性填充多个字节到该内部缓冲区。当程序需要读取字节时,直接从内部缓冲区中读取。当内部缓冲区中数据被读完后,会再次从包含的输入流一次性填充多个字节到该内部缓冲区。mark操作会记录输入流中的某个点,reset操作使得在从输入流中获取新字节之前,再次读取自最后一次mark操作后读取的所有字节。

BufferedOutputStream是缓冲输出流,通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。

下面先介绍下BufferedInputStream。

BufferedInputStream

public class BufferedInputStream extends FilterInputStream {
   

    //缓冲区默认的默认大小
    private static int DEFAULT_BUFFER_SIZE = 8192;

    /**
     * 分派给arrays的最大容量
     * 为什么要减去8呢?
     * 因为某些VM会在数组中保留一些头字,尝试分配这个最大存储容量,
     * 可能会导致array容量大于VM的limit,最终导致OutOfMemoryError。
     */
    private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;

    /**
     * 存放数据的内部缓冲数组。
     * 当有必要时,可能会被另一个不同容量的数组替代。
     */
    protected volatile byte buf[];

    /**
     * 为缓冲区提供compareAndSet的原子更新器。
     * 这是很有必要的,因为关闭操作可以使异步的。我们使用非空的缓冲区数组作为流被关闭的指示器。
     * 该成员变量与buf数组的volatile关键字共同作用,实现了当在多线程环境中操作BufferedInputStream对象时,buf和bufUpdater都具有原子性。
     */
    private static final
        AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
        AtomicReferenceFieldUpdater.newUpdater
        (BufferedInputStream.class,  byte[].class, "buf");

    /**
     * 缓冲区中的字节数。
     */
    protected int count;

    /**
     * 缓冲区当前位置的索引
     */
    protected int pos;

    /**
     * 最后一次调用mark方法时pos字段的值。
     */
    protected int markpos = -1;

    /**
     * 调用mark方法后,在后续调用reset方法失败之前所允许的最大提前读取量。
     * markpos的最大值
     */
    protected int marklimit;

    /**
     * 获取输入流。
     * 判断输入流是否为null,如果为null,抛出异常,否则返回输入流。
     */
    private InputStream getInIfOpen() throws IOException {
        InputStream input = in;
        if (input == null)
            throw new IOException("Stream closed");
        return input;
    }

    /**
     * 获取缓冲区数组。
     * 检查缓冲区数组是否为null,如果为null,抛出异常,否则返回缓冲区数组。
     */
    private byte[] getBufIfOpen() throws IOException {
        byte[] buffer = buf;
        if (buffer == null)
            throw new IOException("Stream closed");
        return buffer;
    }

    /**
     * 构造方法之一
     * 创建一个缓冲区大小为DEFAULT_BUFFER_SIZE的BufferedInputStream。
     */
    public BufferedInputStream(InputStream in) {
        this(in, DEFAULT_BUFFER_SIZE);
    }

    /**
     * 构造方法之一。
     * 创建一个缓冲区大小为size的BufferedInputStream。     *
     */
    public BufferedInputStream(InputStream in, int size) {
        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

    /**
     * 填充缓冲区。
     */
    private void fill() throws IOException {
        //获取缓冲区数组
        byte[] buffer = getBufIfOpen();

        if (markpos < 0)// case1:缓冲区没有被标记。如果缓冲区被标记,那么markpos肯定大于等于0
            pos = 0;:
        else if (pos >= buffer.length)  //缓冲区被标记,且缓冲器已满。pos >= buffer.length说明缓冲区已满。
            if (
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值