序列化: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,我为什么要使用它? 。