今日内容
- 编码表
- 字符流—-操作纯文本文件
- 字符输出流
- 字符输入流
- 字符缓冲流★★★
- 转换流(字符流)
- 对象操作流
- 装饰者模式
- commons-io
-
1.编码表
1.1思考:
既然字节流可以操作所有文件,那么为什么还要学习字符流?
计算机中储存的信息都是用二进制数据表示的:我们在屏幕上看到的英文、汉字等字符都是二进制数转换之后的结果
- 按照编码表规则,将字符存储到计算机中,称之为编码!
- 按照同样的编码表规则,将存储在计算机中的二进制数据解析显示出来,称之为解码!
- 编码和解码使用的码表必须一致,否则会导致乱码
- 简单理解
- 存储一个字符a,首先需要在码表中查到对应的数字时97,然后按照转换成二进制的规则进行存储,称之为编码
- 读取的时候,先把二进制解析出来,再转成97,通过97查找在码表中对应的字符是a,称之为解码
- ASCII码表
- ASCII(American Standard Code For Information Interchange,美国信息交换标准码表)
- 包括了数字字符,英文大小写字符和一些常见的标点符号字符
- 注意:ASCII码表中是没有中文的
- GBK码表
- window系统默认的码表。兼容ASCII码表,也包含了21003个汉字,并支持繁体汉字以及部分日韩文字
- 注意:GBK是中国的码表,一个中文以两个字节的形式存储。但不包含世界上所有国家的文字
Unicode码表
因为字节流一次读写一个字节,而不管在GBK还是UTF-8中,一个中文都是以多个字节,用字节流每次只能都其中的一部分,所以就会出现乱码问题
2.字符输出流
2.1字符流输出介绍
Writer类
- 写入字符流的最顶层的类,是一个抽象类,不能实例化,需要使用其子类FileWriter类
FileWriter类
构造方法
- 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.释放资源
Reader类:
- 读取字符流的最顶层的类,是一个抽象类,不能实例化
- 需要使用其子类FileReader类
FileReader类:
构造方法:
- public FileReader(File file):从指定的File路径中读取数据
- public FileReader(String fileName):从指定的String路劲中读取数据
- 成员方法: | int read() | 一次读一个字符数据 | | —- | —- | | int read(char[] cbuf ) | 一次读一个字符数组数据 |
4.字符缓冲流
4.1字符缓冲流
- BufferedWriter:可以将数据高效的写出
- BufferedReader:可以将数据高效的读入到内存
- 注意:字符缓冲流不具备读写功能,只提供缓冲区,真正的读写还是需要依赖于构造接收的基本的字符流
构造方法:
BufferedWriter类
- void newLine():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符
BufferedReader类
-
5.2转换流分类
InputStreamReader是从字节流到字符流的桥梁
- public InputStreamReader(Input Stream in):创建一个使用默认编码的InputStreamReader
- pulic InputStreamReader(InputStream in , String charsetName):创建使用指定编码的InputStreamReader
OutputStreamWriter是从字符流到字节流的桥梁
可以把对象以字节的形式写道本地文件,直接打开文件,是读不懂的,需要再次用对象操作流读到内存中
6.2对象操作流的分类
ObjectOutputStream:
- 对象操作输出流(对象序列化流):就是将对象写道本地文件中,或者在网络中传输对象
ObjectInputStream:
注意:如果一个类对象想要被序列化,那么此类需要实现Serializable接口
- Serializable接口的含义
- 是一个标记行接口,里面没有任何抽象方法
- 只是一个类实现了此接口,表示此类的对象可以被序列化
- Serializable接口的含义
- 用对象序列化流序列化了一个对象后,假如我们修改了对象所属的Javabean类,读取数据会不会出问题呢?
- 会出问题,会抛出InvalidClassException异常
如果出问题了,如何解决呢?
概述
- 装饰模式指的是在不改变原类,不适用继承的基础上,动态地扩展一个对象的功能
- 不适用继承技术扩展功能,可以降低耦合
使用原则:
- 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.对于不要增强的功能直接调用
- 1.装饰类和被装饰类需要有用共同的父类型
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复制文件的操作。