序列化:java.io.StreamCorruptedException:无效的流标题:0AACED00

我是一名学习我的文件IO技能的学生,我遇到了使用ObjectInputStream从文件中读取对象的问题。 代码一直抛出一个InvalidClassException,我无法找到代码是如何在线投掷或通过反复试验。 这是我的代码:

import java.io.*; import java.util.ArrayList; import java.util.List; public class ReadFromFile { String filename; List os; public ReadFromFile(String filename) { this.filename = filename; os = new ArrayList(); } public Object[] readObject() { try { FileInputStream fis = new FileInputStream(filename); ObjectInputStream ois = new ObjectInputStream(fis); System.out.print("reading\n"); while (true) { os.add(ois.readObject()); System.out.print("read one\n"); } } catch (EOFException e) { return os.toArray(); } catch (FileNotFoundException e) { System.out.print("File not found\n"); return os.toArray(); } catch (ClassNotFoundException e) { System.out.print("Class not found\n"); return os.toArray(); } catch (StreamCorruptedException e) { System.out.print("SC Exception\n"); e.printStackTrace(); return os.toArray(); } catch (InvalidClassException e) { e.printStackTrace(); System.out.print("IC Exception\n"); return os.toArray(); } catch (OptionalDataException e) { System.out.print("OD Exception\n"); return os.toArray(); } catch (IOException e) { System.out.print("IO Exception\n"); return os.toArray(); } } } 

我写了所有单独的catch块来弄清楚抛出了什么exception,它总是抛出InvalidClassException。

这也是我的树类:

 import java.io.Serializable; public class Tree implements Serializable { private static final long serialVersionUID = -310842754445106856L; String species; int age; double radius; public Tree() { this.species = null; this.age = 0; this.radius = 0; } public Tree(String species, int age, double radius) { this.species = species; this.age = age; this.radius = radius; } public String toString() { return species + ", age: " + age + ", radius: " + radius; } } 

这是我的写文件function:

 public boolean write(Object object) { try { File f = new File(filename); FileOutputStream fos = new FileOutputStream(f,true); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(object + "\n"); oos.close(); } catch (FileNotFoundException e) { System.out.print("File Not Found\n"); return false; } catch (IOException e) { System.out.print("IOException\n"); return false; } return true; } 

感谢您的知识……

堆栈跟踪:

 SC Exception java.io.StreamCorruptedException: invalid stream header: 0AACED00 at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:806) at java.io.ObjectInputStream.(ObjectInputStream.java:299) at ReadFromFile.readObject(ReadFromFile.java:17) at WriteAndRecord.main(WriteAndRecord.java:21) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 

进程以退出代码0结束

  java.io.StreamCorruptedException: invalid stream header: 0AACED00 

这是由附加到FileOutputStream.引起的FileOutputStream. 正如我在上面的评论中提到的,你不能附加到ObjectOutputStream编写的流,至少没有特殊措施。 保持文件 ObjectOutputStream打开,直到您编写了要写入的所有对象,然后关闭它,然后从中反序列化。

NB正如我也提到过的,

 while ((object = in.readObect()) != null) 

不是一个有效的对象读取循环。 readObject()在流结束时不返回null:它抛出EOFException 。 只要你编写一个,就可以在流中的任何地方出现null 。 循环的正确forms是:

 try { for (;;) { Object object = in.readObject(); // ... } } catch (EOFException exc) { // end of stream } // other catch blocks ... 

NB 2这个:

 oos.writeObject(object + "\n"); 

应该是公正的

 oos.writeObject(object); 

否则你无意中调用toString()并且无意义地追加一个行终止符,因此readObject()的结果将是一个String,而不是原始对象。

我认为这是由于缺少serialVersionUID引起的。

无论何时序列化对象,ClassLoader都需要validation新加载的对象以validation它并确保其兼容性。 为此,您只需要在类中定义一个字段,如下所示:

 private static final long serialVersionUID = 12358903454875L; 

你的IDE也可能会给你一个警告,指出缺少它(Eclipse会这样做)。

这应该可以解决您的问题。

你可以在Jon Skeet的这篇优秀答案中了解更多信息: 什么是serialVersionUID,我为什么要使用它? 。