Сериализация: java.Ио.StreamCorruptedException: недопустимый заголовок потока: 0AACED00

Я студент, практикующий свои навыки ввода-вывода файлов, и я сталкиваюсь с проблемой чтения объектов из файла с помощью 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("readingn");
        while (true) {
            os.add(ois.readObject());
            System.out.print("read onen");
        }
    } catch (EOFException e) {
        return os.toArray();
    } catch (FileNotFoundException e) {
        System.out.print("File not foundn");
        return os.toArray();
    } catch (ClassNotFoundException e) {
        System.out.print("Class not foundn");
        return os.toArray();
    } catch (StreamCorruptedException e) {
        System.out.print("SC Exceptionn");
        e.printStackTrace();
        return os.toArray();
    } catch (InvalidClassException e) {
        e.printStackTrace();
        System.out.print("IC Exceptionn");
        return os.toArray();
    } catch (OptionalDataException e) {
        System.out.print("OD Exceptionn");
        return os.toArray();
    } catch (IOException e) {
        System.out.print("IO Exceptionn");
        return os.toArray();
    }
}
} 

Я написал все отдельные блоки catch, чтобы выяснить, какое исключение было брошено, и он всегда бросает исключение 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;
}
}

и вот моя функция записи в файл:

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 Foundn");
        return false;
    } catch (IOException e) {
        System.out.print("IOExceptionn");
        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)

процесс завершен с кодом выхода 0

2 ответов


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

это вызвано добавлением к FileOutputStream. как я уже упоминал в комментарии выше, вы не можете добавить к потоку написано ObjectOutputStream, по крайней мере, без специальных мер. Сохраните файл и на ObjectOutputStream открыть, пока вы не написали все объекты, которые хотите написать, затем закрыть его, а затем десериализовать из него.

NB как я уже упоминал,

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

не является допустимым циклом чтения объектов. readObject() не возвращает null в конце потока: это броски EOFException. null может произойти в любом месте потока, в любое время вы пишете один. Правильная форма цикла:

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() будет строкой, а не исходным объектом.


Я думаю, что это было вызвано отсутствием serialVersionUID.

всякий раз, когда вы сериализуете объект, загрузчику классов нужно что-то проверить новый загруженный объект, чтобы проверить его и обеспечить его совместимость. Для этого вам просто нужно определить поле в своем классе следующим образом:

private static final long serialVersionUID = 12358903454875L;

ваша IDE, возможно, также дала вам предупреждение о его отсутствии (Eclipse делает это).

Это должно решить вашу проблему.

Вы можете узнать подробнее в этом отличном ответе Джона Скита здесь:что такое serialVersionUID и почему я должен его использовать?.