java序列化多次序列化到同一个文件及反序列化的问题

这几天上班看了点java的基础知识点,看到介绍序列化的基本问题是都是以介绍序列化一个和反序列化一个对象为例的,依此就想到了要是序列化一次多个序列化对象,再或者不同时间多次序列化对象怎么做,于是动手试了下,发现了不少问题,由于是小菜搞了好久上网找,才得以解决问题,废话不多说了,下面直接进入正题。
     (一).java序列化的基本原理知识
       参考转自:http://yuyiming.iteye.com/blog/1277089
该博客里面基本的介绍,这里不过多废话了。
      (二).一次序列化多个对象及多次序列化产生的问题
       对于一次序列化多个对象的话,就是多次调用writeObject()方法就可以了。然而要注意的一点就是在一次的序列化的过程中(写入文件到关闭文件的过程为一次序列化过程),ObjectOutputStream对象写对象的话,会写入一个header,也就是一次序列化的过程中会在文件开始的地方写入一个Header的信息到文件中,于此在多次序列化的过程中(如序列化一次关闭文件后,可能又需要往文件中序列化其他对象),此时就会继续在文件末尾(本次序列化的开头)写入Header的信息,如此如果进行反序列化的对象的时候会报如下错误java.io.StreamCorruptedException: invalid type code: AC,因为这是头的信息而不是对象的信息,为了解决这个办法,就必须在以后序列化的过程中不写入头文件即可:
解决方法:(详细见博客转自http://blog.sina.com.cn/s/blog_6145ed810100z143.html)
1.用同一个ObjectOutputStream写对象
2.但是大部分时候,要不断往某个文件记录对象,这样按照1的说法就要维护一个ObjectOutputStream,但是重启应用时候就会重新创建一个ObjectOutputStream对象,此时如果还是想往刚才那个文件里写对象的话,就会追加一个header。这样在读对象时读到这个位置就会报错。
解决方法是重写ObjectOutputStream的writeStreamHeader()方法
     (三).多次序列化多个对象时的解决方法
     上面解决了多次序列化的问题,为此我们发现他们在发序列化对象的时候,必须要知道序列化了多少 个对象,然后才能循环多少次把对象取出来,这样显然不是很方便,如果我文件和程序关闭了,我下次要是又想反的时候,怎么才知道以前序列化了多少个对象呢?为此我们通过如下的方法来解决,因为在readObject()的时候,每次都是反序列化一个对象,所以我们可以通过一个while(true)的循环来读取,当到文件最后的时候,会抛出EOFFileEnd的一个异常来解决。代码见下
public class SerializableTestListError {
private static List<Student> listStudentObject = new ArrayList<Student>();
private static List<Car> listCarObject = new ArrayList<Car>();
private static List<Object> listObject = new ArrayList<Object>();

public static void main(String[] args) throws IOException {
Student stu1 = new Student(01044444441, "yteng1", 204);
Student stu2 = new Student(00444344441, "yteng2", 421);
Car car1 = new Car("DazsAut00144444444444400o", "ShangHai", 2000400.0);
Car car3 = new Car("DazsAuto114444444441", "ShangHai", 2000400.0);
Car car2 = new Car("For14444444d", "JiangSu", 300040.00);
listObject.add(car2);
listObject.add(car1);
listObject.add(car3);
listObject.add(stu1);
listObject.add(stu2);
writeObject2File(listObject, "D:\\new.txt");
try {
readObjectFromFile("D:\\new.txt");
} catch (SerilizableException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void writeObject2File(List<Object> o, String fileName)
throws IOException {
File file = null;
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
file = new File(fileName);
fos = new FileOutputStream(file, true);
if (file.length() < 1) {
oos = new ObjectOutputStream(fos);
} else {
oos = new MyObjectOutputStream(fos);
}
for (int i = 0; i < o.size(); i++)
oos.writeObject(o.get(i));

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null)
fos.close();
if (oos != null)
oos.close();
} catch (IOException e) {
e.printStackTrace();
}

}

}

public static void readObjectFromFile(String fileName) throws Exception {

FileInputStream fis = null;
ObjectInputStream ois = null;

try {
fis = new FileInputStream(fileName);
ois = new ObjectInputStream(fis);

while (true)
System.out.println(ois.readObject());

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
System.out.println("文件终止!~");
e.printStackTrace(); //此处解决序列化完成后的异常
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
System.out.println("输出结束~");
} finally {
try {
if (fis != null)
fis.close();
if (ois != null)
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}
这里我一次序列化了多个对象。另外我们还可以用流机制来反序列化多个对象,代码如下:
public class SerializableTest {
private static List<Student> listStudentObject=new ArrayList<Student>();
private static List<Car> listCarObject=new ArrayList<Car>();
private static List<Object> listObject=new ArrayList<Object>();
public static void main(String[] args) throws IOException {
Student stu1=new Student(001, "yteng11", 20);
Student stu2=new Student(002,"yteng22",21);
Car car1=new Car("DazsAuto", "ShangHai", 200000.0);
Car car2=new Car("Ford","JiangSu",30000.00);
writeObject2File(stu1,"D:\\date.txt");
writeObject2File(stu2,"D:\\date.txt");
writeObject2File(car1,"D:\\date.txt");
writeObject2File(car2,"D:\\date.txt");

try {
readObjectFromFile("D:\\date.txt");
} catch (SerilizableException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
for(Iterator<Car> iterCar=listCarObject.iterator();iterCar.hasNext();){
System.out.println(iterCar.next());
}
for(Iterator<Student> iterStudent=listStudentObject.iterator();iterStudent.hasNext();){
System.out.println(iterStudent.next());
}

}


    public static void writeObject2File(Object o,String fileName) throws IOException{
FileOutputStream fout=new FileOutputStream(fileName,true);
ObjectOutputStream sout=new ObjectOutputStream(fout);
sout.writeObject(o);
sout.close();
System.out.println("写入对象成功!");
}
public static void readObjectFromFile(String fileName) throws Exception{

FileInputStream fin=new FileInputStream(fileName);
    BufferedInputStream bis=new BufferedInputStream(fin);
ObjectInputStream oip=null;
  while(true){
         try{
            oip=new ObjectInputStream(bis);   //每次重新构造对象输入流
         }
         catch(EOFException e)
        {
           e.printStackTrace();
          System.out.println("已达文件末尾");//如果到达文件末尾,则退出循环
          break;
        }
         Object object=new Object(); 
         object=oip.readObject();
         if(object instanceof Student) {  //判断对象类型
        listStudentObject.add((Student)object);
        }
         else if(object instanceof Car){
        listCarObject.add((Car)object);
       } 
   }

     oip.close();
     bis.close();
     fin.close();

  }

}
好了,第一次发帖也不知道怎么编辑,比较乱,有错误的话希望大侠指出。

你可能感兴趣的:(java,反序列化,序列化,Serilizable)