I/O复习 三 ObjectInputSream/ObjectOutputStream

对象持久化(Persistence)就是 将对象保存到磁盘文件或者网络中,保存对象的过程实质上就是对象持久化的过程。
* 也就是记录对象的状态以便于将来具有再生的能力。 Java提供了对象流以实现对象的输入输出,也就是实现对象的持久化。
* 需要注意的是在使用对象流之前必须要将该对象序列化。所谓的序列化就是将对象的状态转化成字节流,并且以后可以通过这些值 再生成相同状态的对象。
* 简单来说序列化就是一种用来处理对象流的机制,而对象流也就是将对象的内容进行流化,我们可以对流化后的对象进行读取操作,
* 也可以将流化后的对象传输于网络之间。
*
* 对象序列化,只需要被序列化的类实现Serializable接口就可以了。
* Serializable接口中没有任何的方法,让一个类实现该接口只是为了标注该对象是可以被序列化的,然后就可以对该对象进行持久化。
*
* 注意: 序列化只能保存对象的实例变量,但不能保存类的任何方法和类变量,并且保存的只是变量的值。 对于任何修饰符都不能保存。
* 有些类型的变量是瞬时的,这样的对象也是无法保存的,如:线程对象、或流对象。对于这样的变量,必须用transient关键字标明,否则编译器将报错。
*
* 任何被transient标明的成员变量,将不被保存。
* 考虑到序列化可能涉及对象保存在磁盘上或者网络上,对于一些保密的数据就要加上transient关键字。
*
*
* 对象序列化之后,必须与一定的对象输入/输出流联系起来,通过对象输出流将对象的状态保存下来,再通过对象输入流将对象的状态恢复。
* java提供了ObjectInputStream
* 类和ObjectOutputStream类分别实现了ObjectInput和ObjectOutput。
* ObjectOutput接口用writeObject
* ()方法,可以将对象的状态保存到输出流中。而ObjectInput接口用readObject()方法以从输入流中读入一个对象。
*

Demo:

  1 package com.tai.io;
  2 
  3 import java.io.FileInputStream;
  4 import java.io.FileNotFoundException;
  5 import java.io.FileOutputStream;
  6 import java.io.ObjectInputStream;
  7 import java.io.ObjectOutputStream;
  8 import java.io.Serializable;
  9 
 10 public class PersistenceDome
 11 {
 12     /**
 13      * 对象持久化(Persistence)就是 将对象保存到磁盘文件或者网络中,保存对象的过程实质上就是对象持久化的过程。
 14      * 也就是记录对象的状态以便于将来具有再生的能力。 Java提供了对象流以实现对象的输入输出,也就是实现对象的持久化。
 15      * 需要注意的是在使用对象流之前必须要将该对象序列化。所谓的序列化就是将对象的状态转化成字节流,并且以后可以通过这些值 再生成相同状态的对象。
 16      * 简单来说序列化就是一种用来处理对象流的机制,而对象流也就是将对象的内容进行流化,我们可以对流化后的对象进行读取操作,
 17      * 也可以将流化后的对象传输于网络之间。
 18      * 
 19      * 对象序列化,只需要被序列化的类实现Serializable接口就可以了。
 20      * Serializable接口中没有任何的方法,让一个类实现该接口只是为了标注该对象是可以被序列化的,然后就可以对该对象进行持久化。
 21      * 
 22      * 注意: 序列化只能保存对象的实例变量,但不能保存类的任何方法和类变量,并且保存的只是变量的值。 对于任何修饰符都不能保存。
 23      * 有些类型的变量是瞬时的,这样的对象也是无法保存的,如:线程对象、或流对象。对于这样的变量,必须用transient关键字标明,否则编译器将报错。
 24      * 
 25      * 任何被transient标明的成员变量,将不被保存。
 26      * 考虑到序列化可能涉及对象保存在磁盘上或者网络上,对于一些保密的数据就要加上transient关键字。
 27      * 
 28      * 
 29      * 对象序列化之后,必须与一定的对象输入/输出流联系起来,通过对象输出流将对象的状态保存下来,再通过对象输入流将对象的状态恢复。
 30      * java提供了ObjectInputStream
 31      * 类和ObjectOutputStream类分别实现了ObjectInput和ObjectOutput。
 32      * ObjectOutput接口用writeObject
 33      * ()方法,可以将对象的状态保存到输出流中。而ObjectInput接口用readObject()方法以从输入流中读入一个对象。
 34      * 
 35      * @throws Exception
 36      */
 37     public static void main(String[] args) throws Exception
 38     {
 39         Person p = new Person("张三", "Mauiie", "男");
 40         Person p2 = new Person("p2", "Mauiie", "男");
 41         Person p3 = new Person("p3", "Mauiie", "男");
 42         Student s = new Student("孙俪", "Mauiie", "女");
 43         Person temp = null;
 44         Person temp2 = null;
 45         Student stemp = null;
 46         FileOutputStream fos = new FileOutputStream("c:/data.dat");
 47         ObjectOutputStream oos = new ObjectOutputStream(fos);
 48         oos.writeObject(p);
 49         oos.writeObject(p2);
 50 //        oos.writeObject(p3);
 51         oos.writeObject(s);
 52         oos.close();
 53         System.out.println("已经将p和s对象写入到了 c:/data.dat");
 54 
 55         FileInputStream fis = new FileInputStream("c:/data.dat");
 56         ObjectInputStream ois = new ObjectInputStream(fis);
 57 
 58         temp = (Person) ois.readObject();
 59         temp2 = (Person) ois.readObject();
 60         stemp = (Student) ois.readObject();
 61         
 62         ois.close();
 63         System.out.println(temp.toString());
 64         System.out.println(stemp.toString());
 65         System.out.println(temp2.toString());
 66     }
 67 }
 68 
 69 class Person implements Serializable
 70 {
 71     String Pname;
 72     transient String Pid;
 73     String Psex;
 74 
 75     public Person(String name, String ID, String sex)
 76     {
 77         this.Pname = name;
 78         this.Pid = ID;
 79         this.Psex = sex;
 80     }
 81 
 82     public String toString()
 83     {
 84         return "Name  " + Pname + "  ID  " + Pid + "  sex  " + Psex;
 85     }
 86 }
 87 
 88 class Student implements Serializable
 89 {
 90     String Sname;
 91     transient String Sid;
 92     String Ssex;
 93 
 94     public Student(String name, String ID, String sex)
 95     {
 96         this.Sname = name;
 97         this.Sid = ID;
 98         this.Ssex = sex;
 99     }
100 
101     public String toString()
102     {
103         return "这是Student对象      " + "Name  " + Sname + "  ID  " + Sid
104                 + "  sex  " + Ssex;
105     }
106 }
ObjectInputStream/ObjectOutputStream

运行结果:

已经将p和s对象写入到了 c:/data.dat
Name  张三  ID  null  sex  男
这是Student对象      Name  孙俪  ID  null  sex  女
Name  p2  ID  null  sex  男

值得注意的是:

使用缺省的serializetion的实现时,一个ObjectOutputStream的构造和一个ObjectInputStream的构造必须一一对应。

ObjectOutputStream的构造函数会向输出流中写入一个标识头,而ObjectInputStream会首先读入这个标识头。因此,多次以追加方式向一个文件中写入object时,该文件将会包含多个标识头。

所以用ObjectInputStream来deserialize这个ObjectOutputStream时,将产生StreamCorruptedException。
一种解决方法是可以构造一个ObjectOutputStream的子类,并覆盖writeStreamHeader()方法。被覆盖后的writeStreamHeader()方法应判断是否为首次向文件中写入object?

若是,则调用super.writeStreamHeader();若否,即以追加方式写入object时,则应调用ObjectOutputStream.reset()方法。

如果再向该文件增加对象,新写的对象就读不出了可以参照下面这篇博客,我也遇到这样的问题, 我看了之后也觉得十分受教

http://halzhang.iteye.com/blog/267917

 

原文地址:https://www.cnblogs.com/mauiie/p/ObjectInputSream_ObjectOutputStream.html