缓冲流(高效流)
1.缓冲字节流
- 概念:字节缓冲流(输入、输出):BufferedInputStream(输入)、
BufferedOutputStream(输出)。
- 构造方法
- public BufferedInputStream(InputStream in):
将参数普通的字节输入流,包装成为缓冲的字节输入流。
- public BufferedOutputStream(OutputStream out):
将参数普通的字节输出流,包装成为缓冲的字节输出流。
- 复制文件的步骤
2.缓冲的字符输入流
缓冲的字符输出流:BufferedWriter。
缓冲的字符输入流:BufferedReader。
- 构造方法:
public BufferedWriter(Writer writer):
将参数普通的字符输出流,包装成为缓冲的字符输出流。
public BufferedReader(Reader reader):
将参数普通的字符输入流,包装成为缓冲的字符输入流。
- 底层
BufferedWriter底层有一个char[8192]缓冲数组。
FileWriter底层有一个byte[8192]缓冲数组。
- 额外的方法:new line();
BufferedWriter只有创建new的时候有一些区别,使用起来和FileWriter基本一样。
但是BufferedWriter额外提供了一个换行的方法,备注:这个方法可以自动适应不一样的操作系统,切换到对应的换行符。
- 使用步骤
3.缓冲的字符输出流
- 构造方法
public BufferedReader(Reader reader):将一个普通的字符输入流,包装成为缓冲的字符输入流。
- 底层
BufferedReader底层有一个char[8192]数组
FileReader底层有一个byte[8192]数组
- 区别
创建的时候有一点区别,使用起来和FileReader基本一样。
- 额外的方法
public String readLine():读取一整行字符串,返回值当中不包含换行符。
- 使用步骤:单个字符的方式的读取
- 缺点
- 使用字符数组的方式读取(只有BufferedReader拥有此方法)
- String line:代表一行字符串,line可以为空
- 所以我们用循环输入line
- 为什么要用line去输入?
因为read line一读就是一整行,所以用来判断是否为空了。
4.Practice文字段排序
1. 创建一个缓冲的字符输入流BufferedReader,读取一整行:readLine()
2. 将数字和古文进行拆分:split("\\.")-->String[]
3. 将数字、古文两个部分放在对照关系Map当中,创建:HashMap
4. 读取字符串之后,将两个部分放在Map当中:
4.1 split[0]是字符串,需要转换成为数字:Integer.parseInt
4.2 split[1]是字符串,代表后面的中文
4.3 通过Map的put方法放入<Integer, String>,此时HashMap不保证顺序。
转换流
1.编码
- 概念(字符集、编码(规则)、乱码)
字符集:字符符号和字节数字之间的对照关系表。例如ASCII、Unicode都是对照表。
编码:用几个字节以什么样的方式组合来表示字符集当中的一个文字,这种规则叫做编码。例如GBK、UTF-8都是编码。
乱码:写文件的时候,假设使用GBK编码;但是读文件的时候,使用了UTF-8编码。来回编码规则不一样,导致翻译失败,于是乱码。
- 引出来ASCII字符集、GBKXXX字符集、unicode字符集(有图解)
一般常用的中文,在GBK当中2个字节,在UTF-8当中3个字节。实际开发当中,全世界都在使用UTF-8统一编码。
文件夹中的文件本来是GBK编码的,但是IDEA默认使用的是UTF-8编码,因为编码不一样,就可能出现乱码现象。
- ISO-8859-1字符集(Java web需要谨记的)
2.乱码
- 为什么会出现乱码? (有图解)
你好 -> 查询编码表 ->有了规则 –>字节输出流 -> 文本
如果读入的规则和输出的规则不一样了,那么就会产生乱码。
- 怎么解决?引出来转换流
解决乱码问题,需要通过GBK去读取文件,不用默认的UTF-8。
这就需要使用转换流:InputStreamReader
3.转换流
a) 转换流: InputStreamReader
构造方法
- public InputStreamReader(InputStream in):将参数字节流,按照默认编码转换成为字符流。
- public InputStreamReader(InputStream in, String encoding):第二个参数是指定的编码规则。
InputStreamReader其实就是一个Reader的子类,所以使用起来基本一样。
FileReader只能使用默认编码,无法自己指定编码。InputStreamReader可以自己指定编码。
b) 另一个转换流是:OutputStreamWriter。
构造方法:
public OutputStreamWriter(OutputStream out):使用默认的编码将参数字节流转换成为字符流。
public OutputStreamWriter(OutputStream out, String encoding):第二个参数是自定义的指定编码。
OutputStreamWriter其实就是一个Writer,使用起来和此前的XxxWriter没有什么区别,但是可以指定编码。
4.Practice:GBK-> UTF-8
序列化
1.序列化
- 概念
- 数据:成员变量
- 从对象到文件中(对象数据只要离开内存就是序列化)
- 反序列化(从外面回到内存),objectputStream
- 对象的序列化类:ObjectOutputStream。
构造方法:
public ObjectOutputStream(OutputStream out):参数是字节流,代表希望将对象的数据写到哪里去。 - 常用方法:
public void writeObject(Object obj):将参数对象的数据写到对应的流当中。 - 易发错误:NoSerizableException 异常,代表Person类无法序列化,(查看内部,发现Serializable接口(标识接口),代表着没有它不能运行,就是让你知道可以放心的用,类似合格证的作用),但是也是可以忽略它令不参与序列化,其中有个方法:transient关键字。
2.反序列化ObjectInputStream
- 构造方法
public ObjectInputStream(InputStream in):参数字节流,代表从哪里读取字节数据。 - 读对象的方法
public Object readObject():读取得到一个对象
- 为什么用object接收对象,因为无法确定对象,
如果在这个过程中,如果发现对象的类已经不存在了,将会发生ClassNotFoundException
所以需要解决这个异常,
如果接下来想要挨个遍历,需要向下转型,需要再去判断一下(intstanceof)
3.版本问题
- 原因
- 解决办法,我们自己生成序列号,自动生成,需要我们在idea里面设置如下:
Settings -> editor -> code style -> java ->
- 要不要使用这个验证码?业务决定
4.集合的序列化
遍历时,考虑到,向下转型集合的序列化,需要对进行的instensof判断,还要对对象进行判断。
- 下图是序列化
- 下图是反序列化
打印流
1.其他流
System.in 标准的输入流对象
System.out 标准的输出流对象
System.err 错误的输出流对象
2.System.out对象类型就是PrintStream打印流。
- 常用方法
public void println(任意类型):打印并且换行。
public void print(任意类型):只打印,不换行。
- printSream构造方法
如果不希望使用默认的行为,希望让数据可以自定义打印到哪里去,就可以使用方法:
System.setOut(PrintStream out):参数代表输出语句,将数据输出到哪里去。
public PrintStream(String filename):参数是文件路径名。