缓冲流工作原理

关于缓冲流的一些问题

之前I/O复习的时候,有个关于字节缓冲的代码

public class Demo4 {
    public static void main(String[] args) throws IOException {
        //1.创建字节输入流
        FileInputStream fileInputStream = new FileInputStream("D:\\i.txt");
        BufferedInputStream bufferedInputStream 
            						= new BufferedInputStream(fileInputStream);
        //2.创建字节输出流
        FileOutputStream fileOutputStream  = new FileOutputStream("D:\\j.txt");
        BufferedOutputStream bufferedOutputStream 
            						= new BufferedOutputStream(fileOutputStream);
        //3.进行读写
        int num = 0;
        try {
            while ((num = bufferedInputStream.read()) != -1) {
				bufferedOutputStream.write(num);//还是一个字节一个字节的写的
                bufferedOutputStream.flush();
			}
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            //关闭流对象
            fileInputStream.close();
            fileOutputStream.close();
        }
    }
}

我们都知道缓冲流为我们预先开辟了一个8192的缓冲数组。

//BufferedInputStream源码片段
class BufferedInputStream extends FilterInputStream {
	//默认的缓冲大小是8k
    private static int DEFAULT_BUFFER_SIZE = 8192;

那么这8k缓冲数组是有什么用呢?如最上面那个demo看,似乎我们最终还是一个字符一个字符的读写。

//缓冲流
while ((num = bufferedInputStream.read()) != -1) {//num是一个字符的ascii码
    bufferedOutputStream.write(num);//还是一个字符一个字符的写的
    bufferedOutputStream.flush();
}
//非缓冲流
while ((num = fileInputStream.read()) != -1) {
    fileOutputStream.write(num);
    fileOutputStream.flush();
}

在debug模式下我们也能很清楚的看到,确实一个一个字符一个字符的写入文档的。那么这个这个8k用到哪里去了?真的快了吗?

于是做了下面这样的实验

//缓冲流copy文件
public static void copyFileByBuffer(File srcFile,File destFile) throws IOException {
        //1.创建字节输入流
        FileInputStream fileInputStream = new FileInputStream(srcFile);
        BufferedInputStream bufferedInputStream
                = new BufferedInputStream(fileInputStream);
        //2.创建字节输出流
        FileOutputStream fileOutputStream  = new FileOutputStream(destFile);
        BufferedOutputStream bufferedOutputStream
                = new BufferedOutputStream(fileOutputStream);
        //3.进行读写
        int num = 0;
    	
        byte[] buf=new byte[1024*4];
        try {
            while ((num = bufferedInputStream.read(buf)) != -1) {
                bufferedOutputStream.write(buf,0,num);
                bufferedOutputStream.flush();
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            //关闭流对象
            fileInputStream.close();
            fileOutputStream.close();
        }
    }
public static void copyFileBybyte(File srcFile,File destFile) throws IOException {
        //1.创建字节输入流
        FileInputStream fileInputStream = new FileInputStream(srcFile);
        //2.创建字节输出流
        FileOutputStream fileOutputStream  = new FileOutputStream(destFile);
        //3.进行读写
        int num = 0;
        byte[] buf=new byte[1024*4];
        try {
            while ((num = fileInputStream.read(buf)) != -1) {
                fileOutputStream.write(buf,0,num);
                fileOutputStream.flush();
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            //关闭流对象
            fileInputStream.close();
            fileOutputStream.close();
        }
    }
public static void main(String[] args) throws IOException {
    Long startTime=System.currentTimeMillis();
    //4.27GB的一个文件
    copyFileByBuffer(new File("F:\\test.iso"),new File("F:\\test2.iso"));
    Long endTime=System.currentTimeMillis();
    System.out.println(endTime-startTime);//24441

    startTime=System.currentTimeMillis();
    copyFileBybyte(new File("F:\\test.iso"),new File("F:\\test3.iso"));
    endTime=System.currentTimeMillis();
    System.out.println(endTime-startTime);//38365
}

上面的代码我因为文件比较大,都开了一个4k的缓冲区。发现单纯的字节流用的时间差不多是缓冲流的1.5倍。

这就很明显的看出那8k的效率了。

缓冲流8K的工作原理

普通的字节流I/O操作

如果不涉及自定义的缓冲区,操作是这样的:来一个字节,请求一次IO,然后再来一个字节再请求一次IO。

缓冲流的I/O操作

如果如果不涉及自定义的缓冲区,操作起来是这样的:来一个字节,先放入自带的缓冲区,判断缓冲区满没满或者是不是全写完了,是就请求一个IO把8k的数据一次性写出去。

上面的代码,都开了一个4k的缓冲区。但是缓冲流的缓冲区有8k,也就是差不多两个while请求一次IO。

效率区别就是在这里体现的,减少了请求IO的次数。

注意点:

这里我们发现,快的只有1.5倍?不应该是2倍吗?

当buf(我们自己定义的缓冲区大小).length<buffer(缓冲流的缓冲区大小).length。是这样工作的,数据来了先读满整个buffer,然后通过System.arrayCopy把数据copy到buf中。这一步花销了时间。

当buf>buffer时,缓冲流的buffer就不会工作了。

总结

缓冲流之所以能够提高性能,主要是利用了在内存中开辟的buf空间来实现的,减少了直接消耗系统IO资源的次数,从而提高了性能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值