/ / Серіалізація: java.io.StreamCorruptedException: недійсний заголовок потоку: 0AACED00 - java, серіалізація, java-io

Серіалізація: java.io.StreamCorruptedException: неправильний заголовок потоку: 0AACED00 - java, serialization, java-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("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

Відповіді:

3 для відповіді № 1
 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() буде рядком, а не оригінальним об'єктом.


0 для відповіді № 2

Я думаю, що це було викликано відсутністю serialVersionUID.

Щоразу, коли ви серіалізуєте об'єкт, ClassLoaderпотребує чогось, щоб перевірити новий завантажений об’єкт, щоб перевірити його та забезпечити його сумісність. Для цього вам просто потрібно визначити поле у ​​класі так:

private static final long serialVersionUID = 12358903454875L;

Можливо, ваша IDE також дала вам попередження про відсутність цього (Eclipse це робить).

Це має вирішити вашу проблему.

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