栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

白话Java缓冲流(BufferedInputStream,BufferedOutputStream)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

白话Java缓冲流(BufferedInputStream,BufferedOutputStream)

白话缓冲流(BufferedInputStream,BufferedOutputStream)

1. 什么是流

1.1 读写(复制)文件案例 2. 什么是缓冲流

2.1 缓冲流的作用。

2.1.1 缓冲流的逻辑。2.1.2 输入缓冲流案例:2.1.3 输出缓冲流案例(复制文件):

看了整个CSDN,关于缓冲流的文章基本都是模糊不清,晦涩难懂或者复制粘贴的。
这里做一个简单的分享,以免面试的时候被问到那可就阴沟里翻船了。

你的点赞是我分享的动力

其实大多数Java开发人员在工作中很少会接触的IO流。可面试偏偏问得又比较多,所以我们在闲暇时间还是要把基础好好复习一下。

1. 什么是流

流是一个抽象的概念。在我们Java程序中要去读取一个文件的内容,那么读取的这个动作(通道)就叫做输入流;(下图1)
这时候如果我要Java程序要把一些数据输出到电脑本地形成一个文件,那么输出的这个动作(通道)就叫做输出流。(下图2)

1.1 读写(复制)文件案例

我们这里用java代码简单演示一下输入流和输出流的操作(输入流读取文件,输出流创建文件):

    public  static void test1 ()throws IOException{
    1.初始化主备读取的文件对象。
        File file = new File("C:\Users\Administrator\Desktop\博客.txt");
        
    2.初始化改文件的输入流对象。    
        InputStream inputStream = new FileInputStream(file);
        
    3.初始化新的文件的输出流对象。    
        OutputStream outputStream = new FileOutputStream("C:\Users\Administrator\Desktop\博客01.txt");
        
	4.定义byte数组,用于保存输入流读取到的数据,我们这里定义10长度,说明一次读取10位数据。
        byte[] bytes = new byte[10];
        
    5.表示已经读取了多少个字节,如果是 -1,表示已经读取到文件的末尾。
        int len = -1;
        
	6.inputStream.read(bytes)方法返回int数据,表示本次读取到的字节数。-1的话表示文件已经被读完。
        while ((len = inputStream.read(bytes)) != -1){
        
	7.将 bytes数组中从 0 开始,长度为 len 的数据输出到 博客01.txt 文件中
            outputStream.write(bytes,0,len);
        }

        inputStream.close();
        outputStream.close();
    }

由于本文主要讨论缓冲流,这里对基础的IO流就简单带过。

2. 什么是缓冲流

在了解缓冲流之前,我们先要知道流的分类。 从功能上分类,流分为节点流和包装流。

    节点流:简单来说就是普通的输入流输出流,如上面案例中的InputStream/OutputStream 。包装流:包装流、包装流,顾名思义就是将节点流给包装起来的一种流。而我们将要说的缓冲流就是包装流。

我们先看看缓冲流在Java中是怎么定义的。

嗯 ?飘红了,我们去源码中看看构造函数:

    public BufferedInputStream(InputStream in) {
        this(in, DEFAULT_BUFFER_SIZE);
    }

由此我们得到一个定理:

缓冲流的定义需要一个已经实例化的节点流作为参数。

2.1 缓冲流的作用。

缓冲流:目的是缓存作用,加快读取和写入数据的速度。

程序频繁地操作一个资源(如文件),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域中,以后直接从此区域中读取数据即可,因为读内存速度比较快,这样提高性能。在IO中引入缓冲区,主要是提高流的读写效率。

说起来简单,理解起来就很费劲。怎么就加快了读取和写入的速度了呢?

回忆一下目录1.1中的复制文件案例。

	4.定义byte数组,用于保存输入流读取到的数据,我们这里定义10长度,说明一次读取10位数据。
        byte[] bytes = new byte[10];
        
    5.表示已经读取了多少个字节,如果是 -1,表示已经读取到文件的末尾。
        int len = -1;
        
	6.inputStream.read(bytes)方法返回int数据,表示本次读取到的字节数。-1的话表示文件已经被读完。
        while ((len = inputStream.read(bytes)) != -1){
        
	7.将 bytes数组中从 0 开始,长度为 len 的数据输出到 博客01.txt 文件中
            outputStream.write(bytes,0,len);
        }
    我们定义了一个长度为10的数组用来保存每次读取到的字节。循环读取文件,每次读取10个字节,并将这10个字节输出到新的文件中。直到文件被读完。

好,整个逻辑没什么问题,功能也是完成了,是不是就大功告成了呢?
如果你觉得是,那恭喜你,你是一个合格的增删改查工程师!

很显然,还有优化的空间。
我们知道,IO操作时非常浪费性能的一件事,不管是读取文件还是访问数据库。
在高性能的开发中我们都会尽量避免直接访问数据库,所以我们平时会引入缓存这个概念(Redis等)。为什么呢?因为对缓存的读写比IO读写(磁盘读写)性能提升不是一点半点;那IO操作是不是也可以有缓存这个东西呢?

聪明的同学看到这应该发现了,上面的代码虽然没什么问题,但可能会造成十分严重的性能问题:

    我们定义了一个长度为10的数组用来保存每次读取到的字节。循环读取文件,每次读取10个字节,并将这10个字节输出到新的文件中。直到文件被读完。如果文件有1000个字节呢?我要读100次,写100次。如果文件有10000个字节呢?我要读1000次,写1000次。然而每读写一次都是直接从磁盘读写的IO操作,性能极差。这时候有人说了:“我可以一次性多读一点啊,10个字节太小了,我要读1024或者更多,这样IO操作不九就减少了吗?!”。这确实是一个办法,但我们要记住,程序离不开业务,从实际的业务场景来看,我们很多时候需要去指定每次读取的字节数,而且一般不会是特别大数量的。因为读取之后往往会对读取到的数据进行业务逻辑操作。这个时候缓冲流的作用就体现出来了。
2.1.1 缓冲流的逻辑。

看一段代码:

        File file = new File("C:\Users\Administrator\Desktop\博客.txt");
        InputStream inputStream = new FileInputStream(file);
        
	1.为输入流inputStream 定义一个它的包装流:bufferedInputStream 
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);

好,我们去看看这个构造函数做了什么事情:

DEFAULT_BUFFER_SIZE:默认缓存大小(可自定义)。

可以看到,构造函数最后为我们创建了一个长度为8192的数组。数组名是:buf

这个buf数组就是我们一直以来心心念念的缓存

2.1.2 输入缓冲流案例:
        File file = new File("C:\Users\Administrator\Desktop\博客.txt");
        InputStream inputStream = new FileInputStream(file);

        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);


        byte[] bytes = new byte[10];
        int len = -1;
        while ((len = bufferedInputStream.read(bytes)) != -1) {
            System.out.println("读取到的数据:"+new String(bytes));
        }
    我们创建了一个bufferedInputStream 输入缓冲流。这时候bufferedInputStream 会直接读取文件,将文件中的8192个字节先读取出来,保存在buf数组中。好,开始10个字节10个字节得读取。这里得读取就不是从磁盘文件中读取了,而是从内存中的buf数组中读取,性能极佳。
2.1.3 输出缓冲流案例(复制文件):

我们现在利用缓冲流解决了读的问题。那写的时候怎么办呢?还是10个字节10个字节地去写入磁盘吗?

        File file = new File("C:\Users\Administrator\Desktop\博客.txt");
        InputStream inputStream = new FileInputStream(file);
        OutputStream outputStream = new FileOutputStream("C:\Users\Administrator\Desktop\博客01.txt");

1.创建输入缓冲流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        
2.创建输出缓冲流        
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);

        byte[] bytes = new byte[10];
        int len = -1;

        while ((len = bufferedInputStream.read(bytes)) != -1){
3.利用缓冲流,将数据写入到缓存中,待缓存到达了8129后,再一次性写入磁盘。
            bufferedOutputStream.write(bytes,0,len);
        }
        
4.清空缓存区,以免漏掉缓存区中地数据,将里面地数据强制输出。        
        bufferedOutputStream.flush();
        
        bufferedInputStream.close();
        bufferedOutputStream.close();
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/777009.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号