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

强颜欢笑 提交于 2020-01-11 08:47:47

问题


I'm a student practicing my File IO skills and I am coming up against a problem with reading Objects from a file using ObjectInputStream. The code is consistently throwing an InvalidClassException and I can't find how the code is throwing it online or by trial and error. Here's my code:

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();
    }
}
} 

I wrote all of the separate catch blocks to figure out what Exception was being thrown and it always throws the InvalidClassException.

Here also is my Tree Class:

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;
}
}

And here is my write to file 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;
}

Your knowledge is appreciated...

Stack trace:

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)

Process finished with exit code 0


回答1:


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

This is caused by appending to the FileOutputStream. As I mentioned in a comment above, you can't append to a stream written by ObjectOutputStream, at least not without special measures. Keep the file and the ObjectOutputStream open until you've written all the objects you want to write, then close it, then deserialize from it.

NB As I also mentioned,

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

is not a valid object-reading loop. readObject() doesn't return null at end of stream: it throws EOFException. null can occur anywhere in the stream, any time you write one. The correct form of the loop is:

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

NB 2 This:

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

should be just

oos.writeObject(object);

Otherwise you're implicity calling toString() and pointlessly appending a line terminator, so the result of readObject() will be a String, not the original object.




回答2:


I think this was caused by the lack of a serialVersionUID.

Whenever you serialize an object, the ClassLoader needs something to verify the new loaded object against to verify it and ensure its compatibility. In order to do this, you just need to define a field in your class like this:

private static final long serialVersionUID = 12358903454875L;

Your IDE may have also given you a warning stating the lack of it (Eclipse does this).

This should solve your problem.

You can learn more in this excellent answer by Jon Skeet here: What is a serialVersionUID and why should I use it?.



来源:https://stackoverflow.com/questions/33620323/serializationjava-io-streamcorruptedexception-invalid-stream-header-0aaced00

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!