缓冲流、转换流、序列化流
目录
一、缓冲流
1.缓冲流的作用
缓冲流又叫增强流,用来给四大基本流做性能方面的加强。
2.缓冲流的分类
字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter
3.字节缓冲流的介绍和使用
(1)字节缓冲流的构造
public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。
public BufferedOutputStream(OutputStream out) : 创建一个新的缓冲输出流。
4.字符缓冲流的介绍和使用
(1)字符缓冲流的构造
public BufferedReader(Reader in) :创建一个 新的缓冲输入流。
public BufferedWriter(Writer out) : 创建一个新的缓冲输出流。
(2)特有方法
BufferedReader: public String readLine() : 读一行文字。
BufferedWriter: public void newLine() : 写一行行分隔符,由系统属性定义符号。
5.综合练习:文本排序
HashMap<String, String> linemap = new HashMap<>();
//创建流对象
try (BufferedReader br = new BufferedReader(new FileReader("出师表"));
BufferedWriter bw = new BufferedWriter(new FileWriter("出师表02.txt"));) {
String line = null;
//读取数据
while ((line = br.readLine()) != null) {
//解析文本
String[] split = line.split("\\.");
//保存到集合
linemap.put(split[0], split[1]);
}
//遍历集合
for (int i = 1; i <= linemap.size(); i++) {
//获取map中文本
String value = linemap.get(String.valueOf(i));
//写出拼接文本
bw.write(i + "." + value);
//换行
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
二、转换流
1.字符编码
就是一套自然语言的字符与二进制数之间的对应规则。
编码:字符通过编码转成对应的码值(看的懂的变为看不懂的)
解码:码值通过解码转成对应的字符(看不懂的变为看的懂的)
2.字符集
是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。
3.编码引出的问题
在IDEA中,使用FileReader 读取项目中的文本文件。由于IDEA的设置,都是默认的UTF-8 编码,所以没有任何问题。但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码。
4.InputStreamReader类
转换流java.io.InputStreamReader ,是Reader的子类,是从字节流到字符流的桥梁。
(1)构造方法
InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流。
InputStreamReader(InputStream in, String charsetName) : 创建一个指定字符集的字符流。
5.OutputStreamWriter类
转换流java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁。
(1)构造方法
OutputStreamWriter(OutputStream in) : 创建一个使用默认字符集的字符流。
OutputStreamWriter(OutputStream in, String charsetName) : 创建一个指定字符集的字符流。
三、序列化流
1.什么是序列化流
Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的数据等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。
2.ObjectOutputStream类的使用
(1)构造方法
public ObjectOutputStream(OutputStream out) : 创建一个指定OutputStream的ObjectOutputStream。
(2)序列化操作的前提
一个对象要想序列化,必须满足两个条件:
①该类必须实现java.io.Serializable 接口, Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException 。
②该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰。
(3)写出对象方法
public final void writeObject (Object obj) : 将指定的对象写出。
3.ObjectInputStream类的使用
(1)构造方法
public ObjectInputStream(InputStream in) : 创建一个指定InputStream的ObjectInputStream。
(2)反序列化操作的异常分析
①InvalidClassException异常
当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException 异常。发生这个异常的原因如下:
A.该类的序列版本号与从流中读取的类描述符的版本号不匹配
B.该类包含未知数据类型
C.该类没有可访问的无参数构造方法
Serializable 接口给需要序列化的类,提供了一个序列版本号。serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
②ClassNotFoundException异常
序列化前后,被序列化类被删除了。
(3)读取对象方法
public final Object readObject () : 读取一个对象。
4.序列化多个对象练习
分析:
(1)把若干学习对象 ,保存到集合中。
(2)把集合序列化。
(3)反序列化读取时,只需要读取一次,转换为集合类型。
(4)遍历集合,可以打印所有的学生信息
代码如下:
public class Student implements Serializable {
private static final long serialVersionUID = 8002194731998770433L;
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public static void main(String[] args) throws Exception {
// 创建 学生对象
Student student = new Student("老王", 20);
Student student2 = new Student("老张", 22);
Student student3 = new Student("老李", 24);
ArrayList<Student> arrayList = new ArrayList<>();
arrayList.add(student);
arrayList.add(student2);
arrayList.add(student3);
// 序列化操作
serializ(arrayList);
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("list.txt"));
// 读取对象,强转为ArrayList类型
ArrayList<Student> list = (ArrayList<Student>) ois.readObject();
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println(s.getName() + "‐‐" + s.getAge());
}
}
private static void serializ(ArrayList<Student> arrayList) throws Exception {
// 创建 序列化流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.txt"));
// 写出对象
oos.writeObject(arrayList);
// 释放资源
oos.close();
}
四、打印流PrintStream
1.介绍
作用:用来打印各种数据类型
特点:
a.永远不会抛出IOException
b.不需要关心字符字节,打印什么就是什么
2. 构造方法
public PrintStream(String fileName) : 使用指定的文件名创建一个新的打印流。
PrintStream(OutputStream out): 创建一个新的打印流。
PrintStream(File file): 使用指定的文件创建一个新的打印流。
3.小练习:改变打印流向
// 调用系统的打印流,控制台直接输出97
System.out.println(97);
// 创建打印流,指定文件的名称
PrintStream ps = new PrintStream("ps.txt");
// 设置系统的打印流流向,输出到ps.txt
System.setOut(ps);
// 调用系统的打印流,ps.txt中输出97
System.out.println(97);
上一篇: Ubuntu Android源码以及内核下载与编译
下一篇: 【缓冲流、转换流】