文章目录
序列化与反序列化
概述
序列化: 就是使用流的技术将对象中的数据保存到文件中。
反序列化: 就是使用流的技术将文件中的数据读取到对象中。
使用到的流技术
序列化:ObjectOutputStream
反序列化:ObjectInputStream
ObjectOutputStream介绍 (序列化)
构造:
ObjectOutputStream(OutputStream out)
参数可以传入这两个:FileOutputStream,BufferedOutputStream
关键方法:
writeObject(Object obj) 将指定的对象写入文件。
使用前提:
被写入对象所属的类必须要实现 Serializable 接口。
注意: 建议添加
给该类指定的序列化号,是为了防止序列化后,改动代码所带来的问题,
所以我们指定一个固定的序列化号,使得每次序列化的编号都是固定的,这样就能解决一系列的问题。
public static final long serialVersionUID = 42L;
如果不想序列化某个字段的话,可以在该字段上加上:transient 关键字。
使用格式:修饰符 transient 数据类型 变量名;
ObjectOutputStream演示
public class Student implements Serializable {
//给定序列号防止改动带来的问题
public static final long serialVersionUID = 42L;
private String name;
private String sex;
private Integer age;
public Student() {
}
public Student(String name, String sex, Integer age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
'}';
}
}
测试类:
public class Demo{
public static void main(String[] args) {
Student s = new Student("迪丽热巴", "女", 20);
try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\a.txt"))){
oos.writeObject(s);
}catch (IOException e){
e.printStackTrace();
}
}
}
存储到文件中的结果:虽然我们看不懂但是这是正确的,不用担心。我们在反序列化后就能够看懂了。
�� sr cn.itheima.Work3.StudentC ϖo�Y� L aget Ljava/lang/Integer;L namet L
java/lang/String;L sexq ~ xpsr java.lang.Integer⠤���8 I valuexr j
ava.lang.Number������ xp t 迪丽热巴t 女
ObjectInputStream介绍 (反序列化)
构造:
ObjectInputStream(InputStream in)
参数可以传入这两个:FileInputStream,BufferedInputStream
关键方法:
Object readObject() 将指定文件的内容读取到对象中。
使用前提:
被写入对象所属的类必须要实现 Serializable 接口。
注意:
反序列化操作的文件一定是序列化时操作的文件。
ObjectInputStream演示
public class Demo{
public static void main(String[] args) {
try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\a.txt"))){
Student stu = (Student) ois.readObject();
System.out.println(stu);
}catch (Exception e){
e.printStackTrace();
}
}
}
输出结果:可以看到经过序列化以后,保存到Student对象中,就能够看懂了。
Student{name='迪丽热巴', sex='女', age=20}
拓展
需求:同时序列化多个Student对象和同时反序列化多个Student对象
如果单纯的使用死循环进行反序列化,会出现 EOFException (文件异常到达结尾)异常。
如果不知道文件中有多少个对象,可以使用序列化集合的方式来进行操作。
/*
如果有不想被序列化的字段可以加上这个transient关键字
使用格式:修饰符 transient 数据类型 变量名;
*/
public class Person implements Serializable {
//给定序列号防止改动代码带来的问题 (后面的值可以任意写)
public static final long serialVersionUID = 40L;
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类:
public class Demo{
public static void main(String[] args) {
//writerObjectDemo();
readerObjectDemo();
}
/**
* 演示:反序列化 将文件中的数据存储到Person对象中
* 需要使用的类:ObjectInputStream
* 方法:readObject
*/
private static void readerObjectDemo() {
try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("G:\\writerPerson.txt"))){
ArrayList<Person> list = (ArrayList<Person>) ois.readObject();
for (Person p : list){
System.out.println(p);
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 演示:序列化 将Person对象存入文件中
* 需要使用的类:ObjectOutputStream
* 方法:writeObject
*/
private static void writerObjectDemo() {
try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("G:\\writerPerson.txt"))){
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("张三",18));
list.add(new Person("猪皮",20));
list.add(new Person("丽斯",20));
oos.writeObject(list);
}catch (IOException e){
e.printStackTrace();
}
}
}
结果:
Person{name='张三', age=18}
Person{name='猪皮', age=20}
Person{name='丽斯', age=20}