8.0、Java_IO流 - 如何利用缓冲区提高读写效率 ?

8.0、Java_IO流 - 如何利用缓冲区提高读写效率 ?

简单介绍:

        FileInputStream 通过字节的方式读取文件,适合读取所有类型的文件(图像、视频、文本文件等);Java 也提供了 FileReader 字符流 专门读取文本文件;

        FileOutputStream 通过字节的方式写数据到文件中,适合所有类型的文件;Java 也提供了 FileWriter 字符流 专门写入文本文件;

我们先用案列来了解一下,FileInputStream 和 FileOutputStream  ->

事先准备好一张图片 - 阿尼亚.jpg ->

案例 :创建 FileDemo2.java 文件,如下所示 ->

public class FlieDemo2 {
    public static void main(String[] args) throws FileNotFoundException {
        FileInputStream file = null;
        FileOutputStream file2 = null;
        try {
            //获取 D 盘下的 阿尼亚.jpg 文件
            file  = new FileInputStream("D:/阿尼亚.jpg");
            //获取 D 盘下的 pic.jpg 文件
            file2 = new FileOutputStream("D:/pic.jpg");
            int tmp = 0;
            while((tmp = file.read()) != -1) {
                //一个字节一个字节读取 阿尼亚.jpg 文件
                System.out.println(tmp);
                //将每一个读取出来的字节数据再写到pic.jpg 文件中去
                file2.write(tmp);
            }
        }catch(Exception e) {
            e.printStackTrace();
        //关闭流
        }finally {
            try {
                if(file != null) {
                    file.close();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

执行main方法后输出结果如下所示 ->

 pic.jpg打开后如下所示 ->

说明我们成功将 阿尼亚.jpg 文件读取,且将读取出来的内容写入到了 pic.jpg 文件中;

数据缓冲区:

        看完这个案例之后明显的会感觉到有一个问题,那就是文件读写的效率太慢了,读一个写一个;
打个比方 ->
        我们在超市买了 100 斤大米,然后需要把这 100 斤大米扛回家,一次性肯定拿不动 100 斤,所以按照 案例 的方式就相当于我们一次拿一粒米回家,到家后每次从手中放下一粒米,再回到超市去继续拿......这样要拿放 N 次才能把这 100 斤拿完回家,显而易见效率低的不行......

我给大家提供两种解决方案,如下所示:

【解决方案 1】 
        我们可以做一个一次能装 20 斤大米的包,然后每次就能拿 20 斤大米,到家后每次从手中放下 20 斤大米,把包再拿回超市继续拿,拿五次就能完成;

注意 ->
        这里的包其实就相当于是创建了一个 数据缓冲区 [ 代码:byte[ ] buff = new byte(1024);缓冲区的大小必须为 2 的次幂 ] ;他能解决我们数据读写效率低下的问题;

用代码稍作解释 ->

FileInputStream fis = new FileInputStream("D:/rice.txt");

//创建缓冲区,大小为 1024 byte

byte[ ] buff = new byte[1024]; 

//一次拿一粒大米

fis.read();

//一次拿 20 斤大米

fis.read(buff);

FileOutputStream fos = new FileOutputStream("D:/home.txt");

//创建一个大小为 1024 的缓冲区,当然缓冲区只创建一次即可,可以复用

byte[ ] buff = new byte[1024];

//一次从手中放下一粒大米

fos.write();

//一次从从手中方法 20 斤大米

fos.write ( buff,起始位置,结束位置 ); 

解决方案 1 ,代码如下所示 ->

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileDemo3 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("D:/阿尼亚.jpg");
            fos = new FileOutputStream("D:/pic.jpg");
            byte[] buff = new byte[1024];
            int tmp = 0;
            //每次读取 1024 个字节的数据,将其放到缓冲区 buff 中
            while((tmp = fis.read(buff)) != -1) {
                //输出流,每次将数组 buff 中,从位置 0 开始一直到上面read()读取到的放在数组中的最后一个字节位置写,将其全部入文件 pic.jpg
                fos.write(buff,0,tmp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        //关闭流
        }finally {
            try {
                if(fos != null){
                    //关闭输出流
                    fos.close();
                }
                if(fis != null){
                    //关闭输出流
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

上述代码中:
        fos.write(buff,0,tmp);
用文件输出流对象调用 write(byte[ ],int,int);方法,[ 解释:每次将数组 buff 中,从位置 0 开始一直到上面 read( ) 读取到的放在数组中的最后一个字节位置写,将其全部入文件 pic.jpg ]

        fis.read(buff);方法返回的是读入缓冲区中的字节数;

【解决方案 2】

         还是上面的案例,假设我们的力气超级大,一次性就能把 100 斤大米扛回去,此时我们就不是借助 20 斤的袋子了,而是创建一个能装 100 斤大米的袋子,把大米放进去,直接一次性扛回家就OK了;

        那么说白了方式二也是借助 缓冲区 来提高读写效率,只不过 缓冲区大小 不是自定义了,而是通过 " 文件输入流对象.available() " 方法去定义,该方法会返回当前输入流对象文件的大小预估值;

//创建文件输入流、文件输出流对象

FileInputStream fis = new FileInputStream("D:/阿尼亚.jpg");

FileOutputStream fos = new FileOutputStream(D:/pic.jpg);

//创建缓冲区 buff,缓冲区大小为 fis.available() ,该方法会预估 file.txt 文件大小

byte[ ] buff = new byte[ fis.available( ) ]; 

//读取文件内容,放到 buff 缓冲区中

fis.read( buff );

//将缓冲区 buff 中的数据写出到 pic.jpg 中

fos.write(buff);

        方案2 的代码与 方案1 代码基本相同,唯一不同之处 -> 就在于缓冲区的大小由 available() 方法来定义;所以这里就不做展示 方案2 代码了;

【 到这里要提醒一下大家 】

        在文件很大很大的情况,就不建议大家用 【解决方案 2】这种方式了,因为虽然省事一次性就搞定了,但是却十分的浪费内存空间资源;
        此时就应该使用 【解决方案 1】,虽然每次要搬多次,但不至于将内存空间资源都占了,最后可能导致程序崩溃;

        总结一句话就是:两种方案都是在用 空间 换取 效率;方案1 用较少的空间换取较低的效率,方案2  用较多的空间换取较高的效率;[ 当然,无论是 方案1 还是 方案2 都比不用缓冲区的效率要高得多得多 ];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值