java之IO篇高级流——缓冲流、转化流、序列化流、打印流、压缩流

前言

上一篇IO流就介绍了File和基本流,这节介绍好用的高级流。

还有IO流的心得:随用随创建,什么时候不用什么时候关闭

目录

前言

一、缓冲流

1.体系图

 2.字节缓冲流

(1)用法

(2)底层原理

3.字符缓冲流

(1)用法

二、转换流 

1.作用

2.示例

三、序列化流和反序列化流

1.序列化流ObjectOutputStream

2.反序列化流ObjectInputStream 

3.关键细节

四、打印流 

1.字节打印流PrintStream

2.字符打印流PrintWriter

3.和标准输出流的关系

 五、压缩流和解压缩流

1.解压缩流ZipInputStream

 2.压缩流ZipOutputStream

(1).压缩单个文件

 (2).压缩文件夹


 

一、缓冲流

缓冲流顾名思义就是要多一个缓冲,加快数据的传输速度。但是相对字符流本身就有缓冲区的来说,字节流得到的增益比较多。

1.体系图

 2.字节缓冲流

原理:底层自带了长度为8192的缓冲区提高性能

(1)用法

1.创建基本字节流对象

2.把基本字节流包装成字节缓冲流

3.读写数据

4.关闭流

1.包装基本字节流 

2.读写数据

缓冲流的读写方法和基本流的一样,write和read系列方法。

 3.释放资源

关闭流还是用close()方法,这里只需要关闭相关的高级流,高级流所包装的基本流在底层是有关闭的,不用写包装的基本流的关闭。

(2)底层原理

比较字节基本流效率提高的原理

包装基本流创建缓冲流,传递一个8192作为缓冲区大小,即字节数组的长度

创建一个长度8192的字节数组,作为缓冲区 

每次写数据,将数据编码后的字节写到缓冲数组 

 

刷新缓冲区(基本字节流的刷新方法是空方法,因为没有缓冲区)

刷新缓冲区其实就是调用基本字节流的write将数据写到文件 

 

3.字符缓冲流

(1)用法

字符缓冲流的用法和字节缓冲流的用法一样,都是4步

1.创建基本字符流对象

2.把基本字符流包装成字符缓冲流

3.读写数据

4.关闭流

 1.将基本流包装成高级流

 原理也是底层自带了长度为8192的缓冲区提高性能

 2.字符缓冲流特有的方法

细节:readLine方法在读取的时候,一次读一整行,遇到回车换行结束

               但是他不会把回车换行读到内存当中

              意思就是你用print两次输出readLine读到的数据,两行数据会在一行。

 不同操作系统的换行符是不相同的,使用newLine()方法,可以无视平台限制

二、转换流 

转换流就是,字符流和字节流之间的桥梁,用于字节流和字符流之间的转换。

 为什么会有转换流?因为字节流想要使用字符流的方法。还有指定字符集读写(这个作用在JDK11就被淘汰了,JDK11时的Reader输入字符流的构造器就可以传入指定的字符集,底层原理就是输入字符流继承了InputStreamRead,实现字符集的指定)。

1.作用

InputStreamReader:将字节流转换为字符流

OutputStreamWriter:将字符流转换为字节流

2.示例

指定GBK读数据

指定GBK写数据 

 以GBK读,以UTF-8写

字节流用缓冲字符流的特殊方法实现一行一行读

三、序列化流和反序列化流

在数据库或文件系统中存储复杂数据对象时,序列化可以将对象转换为字节流,便于存储和后续读取。加密存储,防止用户更改数据。

1.序列化流ObjectOutputStream

作用就是,将程序中的对象序列化到文件中。

构造器和方法

示例 

对象想要放入序列化流就必须实现Serializable接口 

2.反序列化流ObjectInputStream 

作用就是,把序列化到本地文件中的对象,读取到程序中来

构造器和方法

示例 

3.关键细节

实现了 Serializable接口 的类,java会根据这个类的内容,计算一个序列号,将这个类的对象写到文件里面的时候,也会把这个类的序列号写好文件里面。

如果你修改了Javabean中的该类的代码内容,该类的序列号会变化,和反序列化的时候从文件得到的序列号发生冲突,反序列化程序就会报错。

所以如何防止出现这个问题呢?

其实我们只需要将javabean的类的添加一个属性,固定该类的序列号(版本号)就可以了。如下

注意:属性的四个修饰词是固定的,属性名也是

 那么又有一个问题,如果我的一个类的一个成员不想被序列化到文件,要怎么做?

这样其实就要在成员变量前面用transient关键词修饰

 最后一个问题,将多个自定义对象序列化到文件中,但是对象的个数不确定,该如何操作呢?

一般我们不会一个一个对象去序列化到文件中,我们通常将对象放到集合(实现 Serializable接口 )里面 ,再将这个集合序列化到文件里面,反序列化就只需要将一个集合反序列化到程序中就可以了。

案例如下

 注意注意注意:我们一定要先序列化到文件,才有反序列化这个步骤。

四、打印流 

1.字节打印流PrintStream

构造方法

注意:字符打印流是没有缓冲区的,所以开不开自动刷新都是一样的 

成员方法(写到文件) 

2.字符打印流PrintWriter

构造方法

成员方法 

3.和标准输出流的关系

如果你关闭了系统的标准输出流,就必须重新运行程序,不然后面的输出语句输出不到控制台。 

 五、压缩流和解压缩流

1.解压缩流ZipInputStream

用法:

1.创建一个解压缩流对象(参数是zip压缩文件的字节输入流)

2.获取这个解压缩流中的每一个ZipEntry对象

3.对每个对象分文件和文件夹处理

4.每次处理一个ZipEntry对象释放一次资源

解压缩的本质:把压缩包里面的每一个文件或者文件夹读取出来,看作每一个ZipEntry对象拷贝到目的地当中 

public class UnzipStreamDemo {
    public static void main(String[] args) throws IOException {
        File src = new File("D:\\aaa.zip");
        File des = new File("D:\\des");
        unzip(src, des);
    }
    private static void unzip(File src, File des) throws IOException {
        //解压的本质:把压缩包里面的每一个文件或者文件夹读取出来,按照层级拷贝到目的地当中

        //创建一个解压缩流用来读取压缩包中的数据
        ZipInputStream zip = new ZipInputStream(new FileInputStream(src));
        //要先获取到压缩包里面的每一个zipentry对象
        ZipEntry ze;
        while ((ze = zip.getNextEntry()) != null) {
            if (ze.isDirectory()){
                //文件夹:需要在目的地dest处创建一个同样的文件夹
                File dir = new File(des, ze.getName());
                dir.mkdir();
            }else {
                //文件:需要读取到压缩包中的文件,并把他存放到目的地dest文件夹中(按照层级目录进行存放)
                File file = new File(des, ze.getName());
                FileOutputStream fos = new FileOutputStream(file);
                int b;
                while ((b = zip.read()) != -1) {
                    fos.write(b);
                }
                fos.close();
                //表示在压缩包中的一个文件的数据处理完毕了。
                zip.closeEntry();
            }
        }
    }
}

 2.压缩流ZipOutputStream

用法:

1.创建压缩流关联压缩包

2.创建ZipEntry对象,表示压缩包里面的每一个文件和文件夹(参数是相对压缩包的路径)

3.把ZipEntry对象放到压缩包当中

4.把src文件中的数据写到压缩包当中

5.每次处理一个ZipEntry对象释放一次资源

压缩本质:把每一个(文件/文件夹)看成ZipEntry对象放到压缩包中,最终产生一个.zip的压缩包

(1).压缩单个文件

 (2).压缩文件夹

 下面压缩的实现方法,最重要的是每一个ZipEntry对象的路径,是压缩包的路径

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值