序列化:java.io.StreamCorruptedException:无效流头:0AACED00

序列化:java.io.StreamCorruptedException:无效流头:0AACED00,java,serialization,java-io,Java,Serialization,Java Io,我是一名练习文件IO技能的学生,在使用ObjectInputStream从文件中读取对象时遇到了一个问题。代码始终抛出InvalidClassException,我无法找到代码是如何在线或通过反复试验抛出它的。这是我的密码: import java.io.*; import java.util.ArrayList; import java.util.List; public class ReadFromFile { String filename; List<Object> os;

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

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class ReadFromFile {
String filename;
List<Object> 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();
    }
}
} 
这是我的文件写入功能:

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.<init>(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)
SC异常
java.io.StreamCorruptedException:无效的流头:0AACED00
位于java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:806)
位于java.io.ObjectInputStream。(ObjectInputStream.java:299)
在ReadFromFile.readObject(ReadFromFile.java:17)
位于WriteAndRecord.main(WriteAndRecord.java:21)
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
位于sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)中
位于java.lang.reflect.Method.invoke(Method.java:497)
位于com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

进程已完成,退出代码为0

我认为这是由于缺少
serialVersionUID
造成的

每当序列化对象时,类加载器都需要一些东西来验证新加载的对象,以验证它并确保其兼容性。为此,只需在类中定义如下字段:

private static final long serialVersionUID = 12358903454875L;
您的IDE可能也给了您一个警告,指出缺少IDE(Eclipse会这样做)

这应该能解决你的问题

您可以在Jon Skeet提供的这个优秀答案中了解更多信息:

这是由于追加到
FileOutputStream中造成的。
正如我在上面的评论中提到的,您不能追加到
ObjectOutputStream
编写的流中,至少在没有特殊措施的情况下是如此。将文件和
ObjectOutputStream
保持打开状态,直到写入所有要写入的对象,然后关闭它,然后从中反序列化

注意,我也提到过

while ((object = in.readObect()) != null)
不是有效的对象读取循环
readObject()
在流的末尾不返回null:它抛出
EOFEException
null
可以出现在流中的任何位置,也可以在您编写流时出现。循环的正确形式是:

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

oos.writeObject(object + "\n");
应该是公正的

oos.writeObject(object);

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

请同时发布stacktrace。这是确定错误的最佳来源。类
与来源有什么关系?这是一个程序吗?类树应该在类路径中可用,以便能够将对象反序列化到它。若要展开@Mr.V.的注释,
必须对序列化程序和反序列化程序都可见。“阅读一”从来没有打印过,是吗?对不起,我不知道stacktrace是什么。“Tree”类可能是问题的一部分。这些都是项目中的类,因为“Tree”类是公共的,所以它应该对任何东西都可见,对吗?而且,是的,“read one”从未打印过。如果他对类进行了版本控制,这可能是因为缺少
serialVersionUID
。否则不会。@EJP您确定吗?这篇文章似乎支持我的理论,至少简单地看一下OPs代码,因为他似乎在尝试反序列化一个对象。当然,我对序列化不太了解(我通常不使用它),但可能是这样。将这行代码插入到我的“Tree”类中可以让它从文件中读取一个对象,但现在它会抛出StreamCorruptedException。这可能与@EJP所说的某些事情有关。@Gruzz好吧,这很有帮助。在这种情况下,我现在希望EJP对您的问题的评论现在能为您提供一个解决方案:)任意的互联网垃圾,例如您的链接,在本次讨论中没有任何状态。我的参考是,其中指出“每个版本化的类必须标识其能够写入流并且可以从中读取的原始类版本…必须在除第一个版本外的所有版本中声明该值”[强调添加]。但是在你的链接中没有任何东西支持你的断言
serialVersionUID
甚至没有提到。谢谢@EJP。这个答案澄清了很多我不理解的东西!
oos.writeObject(object + "\n");
oos.writeObject(object);