今日内容

  • 编码表
  • 字符流—-操作纯文本文件
    • 字符输出流
    • 字符输入流
    • 字符缓冲流★★★
  • 转换流(字符流)
  • 对象操作流
  • 装饰者模式
  • commons-io
  • 递归

    1.编码表

    1.1思考:

  • 既然字节流可以操作所有文件,那么为什么还要学习字符流?

    • 如果使用字节流,把文本文件中的内容读取到内存时,可能会出现乱码
    • 如果使用字节流,把中文写入文本文件中,也有可能会出现乱码

      1.2编码表介绍

  • 计算机中储存的信息都是用二进制数据表示的:我们在屏幕上看到的英文、汉字等字符都是二进制数转换之后的结果

  • 按照编码表规则,将字符存储到计算机中,称之为编码!
  • 按照同样的编码表规则,将存储在计算机中的二进制数据解析显示出来,称之为解码!
  • 编码和解码使用的码表必须一致,否则会导致乱码
  • 简单理解
    • 存储一个字符a,首先需要在码表中查到对应的数字时97,然后按照转换成二进制的规则进行存储,称之为编码
    • 读取的时候,先把二进制解析出来,再转成97,通过97查找在码表中对应的字符是a,称之为解码
  • ASCII码表
    • ASCII(American Standard Code For Information Interchange,美国信息交换标准码表)
    • 包括了数字字符,英文大小写字符和一些常见的标点符号字符
    • 注意:ASCII码表中是没有中文的
  • GBK码表
    • window系统默认的码表。兼容ASCII码表,也包含了21003个汉字,并支持繁体汉字以及部分日韩文字
    • 注意:GBK是中国的码表,一个中文以两个字节的形式存储。但不包含世界上所有国家的文字
  • Unicode码表

    • 由国际ISO指定,是统一的万国码表,计算机科学领域里的一项业界标准,容纳世界上大多数国家的所有常见文字和符号
    • 但是因为表示的字符太多,所以Unicode码表中的数字不是直接以二进制的形式存储到计算机中的,会先通过UTF-7,UTF-7.5,UTF-8,UTF-16,以及UTF-32的编码方式再存储到计算机,其中最为常见的就是UTF-8.
    • 注意:Unicode是万国码表,以UTF-8编码后一个中文是以三个字节的形式存储

      1.3编码小结

      image-20210415215943288.png

      1.4字节流读中文出现乱码的原因

  • 因为字节流一次读写一个字节,而不管在GBK还是UTF-8中,一个中文都是以多个字节,用字节流每次只能都其中的一部分,所以就会出现乱码问题

    2.字符输出流

    2.1字符流输出介绍

  • Writer类

    • 写入字符流的最顶层的类,是一个抽象类,不能实例化,需要使用其子类FileWriter类
  • FileWriter类

    • 用来写入如字符文件便捷类

      2.2FileWriter的成员

  • 构造方法

    • public FileWriter(File file):往指定的File路径中写入数据
    • public FileWriter(String fileName):往指定的String路径中写入数据
  • 成员方法 | 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) | 写入一个字符串的一部分 |
flush() 刷新流,还可以继续写数据
close() 关闭流,释放资源,但是在关闭之前会刷新流。一旦关闭,就不能再写数据

2.3FileWriter写数据的步骤

  • 1.创建字符输出流对象
    • 注意事项:
      • 如果文件不存在,就创建。但是要保证父级路径存在
      • 如果文件存在就清空
  • 2.写数据
    • 注意事项:
      • 写出int类型的整数,实际写出的是整数在码表上对应的字母
      • 写出字符串数据,是把字符串本身原样写出
  • 3.释放资源

    • 注意事项:
      • 每次使用完必须要释放资源

        3.字符输入流

        3.1字符输入流介绍

  • Reader类:

    • 读取字符流的最顶层的类,是一个抽象类,不能实例化
    • 需要使用其子类FileReader类
  • FileReader类:

    • 用来读取字符文件的便捷类

      3.2FileReader的成员

  • 构造方法:

    • public FileReader(File file):从指定的File路径中读取数据
    • public FileReader(String fileName):从指定的String路劲中读取数据
  • 成员方法: | int read() | 一次读一个字符数据 | | —- | —- | | int read(char[] cbuf ) | 一次读一个字符数组数据 |

4.字符缓冲流

4.1字符缓冲流

  • BufferedWriter:可以将数据高效的写出
  • BufferedReader:可以将数据高效的读入到内存
  • 注意:字符缓冲流不具备读写功能,只提供缓冲区,真正的读写还是需要依赖于构造接收的基本的字符流
  • 构造方法:

    • public BufferedWriter(Writer out):构造方法中需要接收一个基本的字符输出流
    • public BufferedReader(Reader in):构造方法中需要接收一个基本的字符输入流

      4.2字符缓冲流特有的功能

  • BufferedWriter类

    • void newLine():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符
  • BufferedReader类

    • public String readLine():读取文件一行数据,不包含换行符号,读到文件的末尾返回null

      5.转换流

      5.1转换流的介绍

  • 转换流就是来进行字节流和字符流之间转换的桥梁

    5.2转换流分类

  • InputStreamReader是从字节流到字符流的桥梁

    • public InputStreamReader(Input Stream in):创建一个使用默认编码的InputStreamReader
    • pulic InputStreamReader(InputStream in , String charsetName):创建使用指定编码的InputStreamReader
  • OutputStreamWriter是从字符流到字节流的桥梁

    • public OutputStreamWriter(OutputStream out):创建使用默认字符编码的OutputStreamWriter
    • public OutputStreamWriter(OutputStream out , String chasetName):创建使用指定编码的OutputStreamWriter

      6.对象操作流

      6.1对象操作流介绍

  • 可以把对象以字节的形式写道本地文件,直接打开文件,是读不懂的,需要再次用对象操作流读到内存中

    6.2对象操作流的分类

  • ObjectOutputStream:

    • 对象操作输出流(对象序列化流):就是将对象写道本地文件中,或者在网络中传输对象
  • ObjectInputStream:

    • 对象操作输入流(对象反序列化流):把写到本地文件中的对象读到内存中,或者接收网络中传输的对象

      6.3对象操作流的注意事项

  • 注意:如果一个类对象想要被序列化,那么此类需要实现Serializable接口

    • Serializable接口的含义
      • 是一个标记行接口,里面没有任何抽象方法
      • 只是一个类实现了此接口,表示此类的对象可以被序列化
  • 用对象序列化流序列化了一个对象后,假如我们修改了对象所属的Javabean类,读取数据会不会出问题呢?
    • 会出问题,会抛出InvalidClassException异常
  • 如果出问题了,如何解决呢?

    • 给对象所属的类加一个serialVersionUID
    • private static final long serialVersionUID = 42L;
    • 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现?
      • 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程

        7.装饰设计模式

  • 概述

    • 装饰模式指的是在不改变原类,不适用继承的基础上,动态地扩展一个对象的功能
    • 不适用继承技术扩展功能,可以降低耦合
  • 使用原则:

    • 1.装饰类和被装饰类需要有用共同的父类型
      • 在之前学习过的BufferedWriter和FileWriter就是装饰设计模式
      • BufferedWriter的父类也是Writer
      • 我们把FileWriter的对象传递到BufferedWriter的构造中,那么理解为BufferedWriter是装饰类,FileWriter是被装饰类
      • BufferedWriter对FileWriter的功能做了增强
    • 2.装饰类的构造要接收被装饰类的对象
      • FileWriter fw = new FileWriter(“路径”);
      • BufferedWriter bw = new BufferedWriter(fw);
    • 3.在装饰类中把要增强扩展的功能进行扩展
      • BufferedWriter 和 FileWriter的功能一样,都具备Writer中写数据的功能
      • 但是BufferedWriter提供了缓冲区,相当于对FileWriter功能做了扩展
    • 4.对于不要增强的功能直接调用
      • 不需要增强的功能直接继承父类即可

        8.commons-io工具包(对文件的拷贝做优化)

  • 1.需要导入jar包

  • 主要方法:
    • public static void copyFileToDirectory(final File srcFile , final File destFile):复制文件到另外一个目录下
    • public static void copyDirectoryToDirectory(File src , File dest):复制src目录到dest位置
  • commons-io可以简化IO复制文件的操作。