对象流
作者:互联网
对象流的序列化,与反序列化
序列化: 把内存中的java对象保存在文件中,这个过程叫做序列化(或者叫持久化,钝化)
ObjectOutputStream
存储过程:
1、通过一些算法将这个对象的内部结构转为字节数组,包括类的类名和签名,对象的字段和数组的值以及从初始对象引用的任何其他对象的关闭。并且把字节数组保存到缓冲区
2、将表示对象的字节数组通过fos(FileOutputStream)写入到文件中
反序列化:把java对象从文件中读取到内存中,这个过程叫做反序列化(活化)
ObjectInputStream
Student类
import java.io.Serializable;//要实现这个标记型接口才可以序列化
public class Student implements Serializable {
private int id;
private String name;
private int age;
private String className;
private char sex;
/*
* 添加了对象的属性 Demo06报异常
* 1、对象类在编译的时候,编译器会为这个类产生一个serialVersionUID这个信息在类的.class文件中
* 2、使用ObjectOutputStream去存储这个类的对象的时候会带上serialVersionUID,把它一起存入到文件中
* 3、在ObjectInputStream去读取文件并且恢复(创建)对象的时候和文件中的serialVersionUID和当前的类的.class文件比较
* 如果不一致会报异常InvalidClassException,一致就会创建对象
* */
private static final long serialVersionUID=1L;
//给的serialVersionUID为定值,即时在写和读值之间对类的修改也不会影响对象的反序列化
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public Student() {
}
public Student(int id, String name, int age, String className) {
this.id = id;
this.name = name;
this.age = age;
this.className = className;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", className='" + className + '\'' +
'}' + "\n";
}
}
对象输出流ObjectOutputStream:
public class Demo01 {
/*
* 把java对象字节输出到文件,手动打开文件会有一部分乱码
* */
public static void main(String[] args) {
ObjectOutputStream oos = null;
try {
Student gzh = new Student(20188747, "gzh", 20, "xxxx");//创建一个对象
FileOutputStream fos = new FileOutputStream("C:\\Users\\GzhAnkh\\Desktop\\FileApiDemo03\\Demo01.txt");
oos = new ObjectOutputStream(fos);
oos.writeObject(gzh);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
对象输入流ObjectInputStream:
ObjectInputStream的作用:将保存在文件中的对象数据读取到内存中,并且重新新生成对象
/*
* 构造方法:ObjectInputStream(InputStream in)
*
* 核心方法:Object readObject()
* */
public class Demo03 {
public static void main(String[] args) {
ObjectInputStream ois = null;
try {
FileInputStream fis = new FileInputStream("C:\\Users\\GzhAnkh\\Desktop\\FileApiDemo03\\Demo01.txt");
ois = new ObjectInputStream(fis);
Object o = ois.readObject();
// 通过对象流创建的对象并不是调用对象的构造方法,而是JVM内部创建的对象。也是对象的深拷贝实现方式之一.
System.out.println(o);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(ois!=null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
在对存储了对象的文件进行读取之前,对对象实体类进行了修改,之后再对文件进行读取
public class Demo06 {
/*
* 1、对象类在编译的时候,编译器会为这个类产生一个serialVersionUID这个信息在类的.class文件中
* 2、使用ObjectOutputStream去存储这个类的对象的时候会带上serialVersionUID,把它一起存入到文件中
* 3、在ObjectInputStream去读取文件并且恢复(创建)对象的时候和文件中的serialVersionUID和当前的类的.class文件比较
* 如果不一致会报异常InvalidClassException,一致就会创建对象
* (我感觉:应该是在创建对象的时候,对象类属性发生改变,就不知道是创建文件中的对象,还是创建类中的对象,所有要设置比较serialVersionUID)
* 在执行对象在程序与文件的读写操作的时候
*
* */
//文件保存的是没有修改过的类的对象
//在Student类中添加了属性,已经注释了,不注释运行Demo06就报异常
//在Student类中给定serialVersionUID为定值,即时在写和读值之间对类的修改也不会影响对象的反序列化
private static final String PATH = "C:\\Users\\GzhAnkh\\Desktop\\FileApiDemo03\\Demo04.ser";
public static void main(String[] args) {
ObjectInputStream ois = null;
try {
FileInputStream fis = new FileInputStream(PATH);
ois = new ObjectInputStream(fis);
Object o = ois.readObject();
Object o1 = ois.readObject();
System.out.println(o + "\n" + o1);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
transient: 标注的属性不会被序列化。不会存储到文件中
public class Demo09 {
public static void main(String[] args)throws Exception {
Bird bird = new Bird("孔雀", 20);
FileOutputStream fos = new FileOutputStream("C:\\Users\\GzhAnkh\\Desktop\\bird.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(bird);
oos.close();
System.out.println("------------------------");
FileInputStream fis = new FileInputStream("C:\\Users\\GzhAnkh\\Desktop\\bird.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
Object object = ois.readObject();
System.out.println(object);
}
}
/*
* transient修饰符,瞬派
* */
class Bird implements Serializable {
private String kind;
private transient int age;
@Override
public String toString() {
return "Bird{" +
"kind='" + kind + '\'' +
", age=" + age +
'}';
}
public Bird(String kind, int age) {
this.kind = kind;
this.age = age;
}
}
小练习:使用对象流保存一个含有100个学生的集合。
/*
* 分析: 1、准备一个集合
* 2、往集合中添加100个学生对象 *
* 3、创建对象输出流
* 4、输出List对象
* 5、关闭流, 释放资源。
* */
public class Demo10 {
public static void main(String[] args) {
ArrayList<Student> students = null;
ObjectOutputStream objectOutputStream = null;
try {
students = new ArrayList<>();
for (int i = 0; i < 100; i++) {
Student student = new Student(2018000 + i, "name" + i, i + 10, "j1o9");
students.add(student);
}
System.out.println(students.size());
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\GzhAnkh\\Desktop\\Students.ser");
objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(students);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
objectOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
if (objectOutputStream != null) {
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
标签:String,对象,age,new,ois,public 来源: https://www.cnblogs.com/Gzh001007/p/15054570.html