BIO中的文件流(FileInputStream,FileOutputStream)及缓冲流(bufferedInputStream,bufferedOutputStream)

首先是文件输入及输出流的基本使用

public static void test1() throws Exception {
        long start = System.currentTimeMillis();
        File fromFile = new File("/Users/mouxiaoshi/IdeaProjects/pro-test/[BD影视分享bd2020.com]电u惊魂8.Jigsaw.2017.HD720P.中英双字.mp4");
        File toFile = new File("/Users/mouxiaoshi/IdeaProjects/pro-test/11[BD影视分享bd2020.com]电u惊魂8.Jigsaw.2017.HD720P.中英双字.mp4");
        FileInputStream fileInputStream = new FileInputStream(fromFile);
        FileOutputStream fileOutputStream = new FileOutputStream(toFile);
        byte[] bytes = new byte[1024];
        int read;
        while ((read = fileInputStream.read(bytes)) != -1) {
            fileOutputStream.write(bytes, 0, read);
        }
        fileOutputStream.close();
        fileInputStream.close();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

在代码中我们用到了自定义的“缓冲区”,将文件读入的字节数据放到bytes数组中,然后批量的写入到输出流

其中fileInputStream.read(bytes)的返回值是读取到数据的长度

复制文件耗时12秒


然后加入缓冲流

 public static void test2() throws Exception {
        long start = System.currentTimeMillis();
        File fromFile = new File("/Users/mouxiaoshi/IdeaProjects/pro-test/[BD影视分享bd2020.com]电u惊魂8.Jigsaw.2017.HD720P.中英双字.mp4");
        File toFile = new File("/Users/mouxiaoshi/IdeaProjects/pro-test/11[BD影视分享bd2020.com]电u惊魂8.Jigsaw.2017.HD720P.中英双字.mp4");
        FileInputStream fileInputStream = new FileInputStream(fromFile);
        FileOutputStream fileOutputStream = new FileOutputStream(toFile);

        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bufferedInputStream.read(bytes, 0, bytes.length)) != -1) {
            bufferedOutputStream.write(bytes, 0, len);
        }
        bufferedOutputStream.close();
        bufferedInputStream.close();
        fileOutputStream.close();
        fileInputStream.close();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

复制文件耗时3.5秒

 

BufferedInputStream中定义了用于储存数据的缓冲区(数组)
protected volatile byte buf[];

当未指定数组的大小是,默认的大小为8192

private static int DEFAULT_BUFFER_SIZE = 8192;

先来看下bufferedInputStream的读操作

public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
}

当读取的位置大于或等于bufferedInputStream中缓重区有限数据标志位时,说明bufferedInputStream中的数据已经读完了,需要填充数据

private void fill() throws IOException {
        //获取缓冲区
        byte[] buffer = getBufIfOpen();
        //判断是否标记
        if (markpos < 0)
            //未标记
            pos = 0;
        else if (pos >= buffer.length)
            //已读完
            if (markpos > 0) {
                //有标记的部分,丢弃不需要的的部分(未标记的部分)标记由mark方法执行标记
                int sz = pos - markpos;
                //复制标记部分到头位置
                System.arraycopy(buffer, markpos, buffer, 0, sz);
                //读取的位置为标志位置的结尾
                pos = sz;
                //标记位置为0
                markpos = 0;
            } else if (buffer.length >= marklimit) {
                //意味着markPos已经失效,用户不可以在进行reRead
                //1. pos位置大于等于缓存长度,且markPos等于零,此时的 pos >= buffer.length 而 buffer.length >= marklimit
                // 故(pos-markPos) = pos > markLimit,也就是说根据 marklimit字段的描述
                // Whenever the difference between pos and markpos exceeds marklimit, then the mark may be dropped by setting markpos to -1.
                //此时buffer的标记位时无效的
                markpos = -1;
                pos = 0;
            } else if (buffer.length >= MAX_BUFFER_SIZE) {
                //大于最大的缓冲大小
                throw new OutOfMemoryError("Required array size too large");
            } else {
                //扩容
                int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
                        pos * 2 : MAX_BUFFER_SIZE;
                if (nsz > marklimit)
                    nsz = marklimit;
                byte nbuf[] = new byte[nsz];
                System.arraycopy(buffer, 0, nbuf, 0, pos);
                if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
                    // Can't replace buf if there was an async close.
                    // Note: This would need to be changed if fill()
                    // is ever made accessible to multiple threads.
                    // But for now, the only way CAS can fail is via close.
                    // assert buf == null;
                    throw new IOException("Stream closed");
                }
                buffer = nbuf;
            }
        //读取新的数据到缓冲剩余空间当中
        count = pos;
        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
        if (n > 0)
        //有效数据位置偏移   
            count = n + pos;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值