Java中的IO流(高级流)

目录

一、缓冲流

1、字符输入流- 一次读取一个字符

a.存在问题

b.

c.文件字符输入流:Reader

 d.字符流一次读取一个字符的优缺点

2、字符输入流- 一次读取一个字符数组

a.文件字符输入流:FileReader

b.常用方法

c.字符流一次读取一个字符数组的优缺点

3、字符输出流

a.文件字符输出流:FileWriter

b.文件字符输出流(FileWriter)写数据出去的API

c.流的关闭与刷新

d. 字节流、字符流的使用场景总结

二、转换流

1、缓冲流概述、字节缓冲流的使用

a.缓冲流概述

b.字节缓冲流性能优化原理

c.字节缓冲流

2、字节缓冲流的性能分析

a.观察性能情况

b.需求:

c.分析

d.代码

e.总结

3、字符缓冲流

a.字符缓冲输入流

b.字符缓冲输入流新增功能

c.字符缓冲输出流

d.字符缓冲输出流新增功能

e.总结

三、转换流

1、问题引出:不同编码读取乱码问题

a.之前我们使用字符流读取中文是否有乱码?

b.如果代码编码和文件编码不一致,使用字符流直接读取还能不乱码吗?

2、字符输入转换流

a.如果如何解决乱码

b.字符输入转换流:InputStreamReader,可以把原始的字节流按照指定编码转换成字符输入流。

3、字符输出转换流

a.字符输入转换流:OutputStreamWriter,可以把字节输出流按照指定编码转换成字符输出流。


一、缓冲流

1、字符输入流- 一次读取一个字符

a.存在问题

字节流读取中文输出会存在什么问题?

答:会乱码。或者内存溢出。

b.

读取中文输出,哪个流更合适,为什么?

答:字符流更合适,最小单位是按照单个字符读取的。

c.文件字符输入流:Reader

作用:

以内存为基准,把磁盘文件中的数据以字符的形式读取到内存中去。

构造器:

构造器

说明

public FileReader​(File file)

创建字符输入流管道与源文件对象接通

public FileReader​(String pathname)

创建字符输入流管道与源文件路径接通

常用方法:

方法名称

说明

public int read()

每次读取一个字符返回,如果字符已经没有可读的返回-1

public int read(char[] buffer)

每次读取一个字符数组,返回读取的字符个数,如果字符已经没有可读的返回-1

 d.字符流一次读取一个字符的优缺点

读取中文字符不会出现乱码(如果代码文件编码一致)。

性能较慢。

2、字符输入流- 一次读取一个字符数组

a.文件字符输入流:FileReader

作用:

以内存为基准,把磁盘文件中的数据以字符的形式读取到内存中去。

b.常用方法

方法名称

说明

public int read()

每次读取一个字符返回,如果字符已经没有可读的返回-1

public int read(char[] buffer)

每次读取一个字符数组,返回读取的字符数,如果字符已经没有可读的返回-1

c.字符流一次读取一个字符数组的优缺点

读取的性能得到了提升。

读取中文字符输出不会乱码。

3、字符输出流

a.文件字符输出流:FileWriter

作用:

以内存为基准,把内存中的数据以字符的形式写出到磁盘文件中去的流。

构造器:

构造器

说明

public FileWriter(File file)

创建字符输出流管道与源文件对象接通

public FileWriter​(File file,boolean append)

创建字符输出流管道与源文件对象接通,可追加数据

public FileWriter​(String filepath)

创建字符输出流管道与源文件路径接通

public FileWriter​(String filepath,boolean append)

创建字符输出流管道与源文件路径接通,可追加数据

b.文件字符输出流(FileWriter)写数据出去的API

方法名称

说明

void write​(int c)

写一个字符

void write​(char[] cbuf)

写入一个字符数组

void write​(char[] cbuf, int off, int len)

写入字符数组的一部分

void write​(String str)

写一个字符串

void write​(String str, int off, int len)

写一个字符串的一部分

c.流的关闭与刷新

方法

说明

flush()

刷新流,还可以继续写数据

close()

关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 

d. 字节流、字符流的使用场景总结

字节流适合做一切文件数据的拷贝(音视频,文本)

字节流不适合读取中文内容输出

字符流适合做文本文件的操作(读,写)

二、转换流

1、缓冲流概述、字节缓冲流的使用

a.缓冲流概述

缓冲流也称为高效流、或者高级流。之前学习的字节流可以称为原始流。

作用:缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能

b.字节缓冲流性能优化原理

字节缓冲输入流自带了8KB缓冲池,以后我们直接从缓冲池读取数据,所以性能较好。

字节缓冲输出流自带了8KB缓冲池,数据就直接写入到缓冲池中去,写数据性能极高了

c.字节缓冲流

 字节缓冲输入流:BufferedInputStream,提高字节输入流读取数据的性能。  

字节缓冲输出流:BufferedOutputStream,提高字节输出流读取数据的性能。

构造器

说明

public BufferedInputStream​(InputStream is)

可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能

public BufferedOutputStream​(OutputStream os)

可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能

2、字节缓冲流的性能分析

a.观察性能情况

b.需求:

分别使用低级字节流和高级字节缓冲流拷贝大视频,记录耗时

c.分析

1.使用低级的字节流按照一个一个字节的形式复制文件。

2.使用低级的字节流按照一个一个字节数组的形式复制文件。

3.使用高级的缓冲字节流按照一个一个字节的形式复制文件。

4.使用高级的缓冲字节流按照一个一个字节数组的形式复制文件。

d.代码

/**
    目标:比较IO流当中的原始流和高级流的性能
 */
public class ByteBufferTimeDemo {
    private static final String SRC_FILE = "C:\\Users\\ls\\Videos\\ce7dc35e4ceda89516453426094290f8.mp4";
    private static final String DEST_FILE = "C:\\Users\\ls\\Videos\\";

    public static void main(String[] args) {
//        copy01();  //使用低级的字节流按照一个一个字节的形式复制文件
        copy02();  //使用低级的字节流按照一个一个字节数组的形式复制文件
//        copy03();  //使用缓流按照一个一个字节复制
        copy04();  //使用缓流按照一个一个字节数组复制
    }

    /**
        使用缓流按照一个一个字节数组复制
     */
    private static void copy04() {
        long startTime = System.currentTimeMillis();
        try(
                //1、创建一个低级的字节输入流与源文件接通
                InputStream is = new FileInputStream(SRC_FILE);
                //a.把原始的字节输入流包装成高级的缓冲字节输入流
                InputStream bis = new BufferedInputStream(is);
                //2、创建低级的字节输出流与目标文件接通
                OutputStream os = new FileOutputStream(DEST_FILE + "舞蹈机器人04.mp4");
                //b.把字节输出流管道包装成高级的缓冲字节输出流管道
                OutputStream bos = new BufferedOutputStream(os);
        ) {
            //3、定义一个字节数组转移数据
            byte[] butter = new byte[1024];
            int len;  //记录每次读取字节数
            while ((len = bis.read(butter)) != -1 ){
                bos.write(butter,0,len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("使用缓流按照一个一个字节数组复制:"+(endTime-startTime)/1000.0+"s");
    }

    /**
     使用缓流按照一个一个字节复制
     */
    private static void copy03() {
        long startTime = System.currentTimeMillis();
        try(
                //1、创建一个低级的字节输入流与源文件接通
                InputStream is = new FileInputStream(SRC_FILE);
                //a.把原始的字节输入流包装成高级的缓冲字节输入流
                InputStream bis = new BufferedInputStream(is);
                //2、创建低级的字节输出流与目标文件接通
                OutputStream os = new FileOutputStream(DEST_FILE + "舞蹈机器人03.mp4");
                //b.把字节输出流管道包装成高级的缓冲字节输出流管道
                OutputStream bos = new BufferedOutputStream(os);
        ){
            //3、定义一个变量记录每次读取得字节(一个一个字节的复制)
            int b;
            while ((b = bis.read()) != -1){
                bos.write(b);
            }

        }
        catch (Exception e){
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("使用缓流按照一个一个字节复制耗时:"+(endTime-startTime)/1000.0+"s");
    }

    /**
        使用低级的字节流按照一个一个字节数组的形式复制文件
     */
    private static void copy02() {
        long startTime = System.currentTimeMillis();
        try(
                //这里面只能放置资源对象,用完会自动关闭;自动调用资源对象的close方法关闭资源(即使出现异常也会做关闭操作)
                //1、创建一个字节输入流管道与原视频接通
                InputStream is = new FileInputStream(SRC_FILE);
                //2、创建一个字节输出流管道与目标文件接通
                OutputStream os = new FileOutputStream(DEST_FILE + "舞蹈机器人02.mp4")
        ) {
            //3、定义一个字节数组转移数据
            byte[] butter = new byte[1024];
            int len;  //记录每次读取字节数
            while ((len = is.read(butter)) != -1 ){
                os.write(butter,0,len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("使用低级的字节流按照一个一个字节数组的形式复制文件耗时:"+(endTime-startTime)/1000.0+"s");
    }

    /**
        使用低级的字节流按照一个一个字节的形式复制文件
     */
    private static void copy01() {
        long startTime = System.currentTimeMillis();
        try(
                //1、创建一个低级的字节输入流与源文件接通
                InputStream is = new FileInputStream(SRC_FILE);
                //2、创建低级的字节输出流与目标文件接通
                OutputStream os = new FileOutputStream(DEST_FILE + "舞蹈机器人01.mp4")
                ){
            //3、定义一个变量记录每次读取得字节(一个一个字节的复制)
            int b;
            while ((b = is.read()) != -1){
                os.write(b);
            }

        }
        catch (Exception e){
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("使用低级的字节流按照一个一个字节的形式复制文件耗时:"+(endTime-startTime)/1000.0+"s");
    }
}

e.总结

建议使用字节缓冲输入流、字节缓冲输出流,结合字节数组的方式,目前来看是性能最优的组合。

3、字符缓冲流

a.字符缓冲输入流

字符缓冲输入流:BufferedReader。

作用:提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能。

构造器

说明

public BufferedReader​(Reader r)

可以把低级的字符输入流包装成一个高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能

b.字符缓冲输入流新增功能

方法

说明

public String readLine()

读取一行数据返回,如果读取没有完毕,无行可读返回null

c.字符缓冲输出流

字符缓冲输出流:BufferedWriter。  

作用:提高字符输出流写取数据的性能,除此之外多了换行功能

构造器

说明

public BufferedWriter​(Writer w)

可以把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能

d.字符缓冲输出流新增功能

方法

说明

public void newLine()

换行操作

e.总结

1.字符缓冲流为什么提高了操作数据的性能?

字符缓冲流自带8K缓冲区

可以提高原始字符流读写数据的性能

三、转换流

1、问题引出:不同编码读取乱码问题

a.之前我们使用字符流读取中文是否有乱码?

没有的,因为代码编码和文件编码都是UTF-8。

b.如果代码编码和文件编码不一致,使用字符流直接读取还能不乱码吗?

会乱码。

文件编码和读取的编码必须一致才不会乱码。

2、字符输入转换流

a.如果如何解决乱码

使用字符输入转换流 可以提取文件(GBK)的原始字节流,原始字节不会存在问题。

然后把字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不乱码了

b.字符输入转换流:InputStreamReader,可以把原始的字节流按照指定编码转换成字符输入流。

构造器

说明

public InputStreamReader(InputStream is)

可以把原始的字节流按照代码默认编码转换成字符输入流。几乎不用,与默认的FileReader一样。

public InputStreamReader(InputStream is ,String charset)

可以把原始的字节流按照指定编码转换成字符输入流,这样字符流中的字符就不乱码了(重点)

3、字符输出转换流

a.字符输入转换流:OutputStreamWriter,可以把字节输出流按照指定编码转换成字符输出流。

构造器

说明

public OutputStreamWriter(OutputStream os)

可以把原始的字节输出流按照代码默认编码转换成字符输出流。几乎不用。

public OutputStreamWriter(OutputStream os,String charset)

可以把原始的字节输出流按照指定编码转换成字符输出流(重点)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

꧁༺๑小王不是程序员๑༻꧂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值