2015-11-09 31 views
6

Sono uno studente che pratica le mie abilità di file I/O e mi imbatto in un problema con la lettura di oggetti da un file utilizzando ObjectInputStream. Il codice genera costantemente InvalidClassException e non riesco a trovare il modo in cui il codice lo sta pubblicando online o per tentativi ed errori. Ecco il mio codice:Serializzazione: java.io.StreamCorruptedException: intestazione stream non valida: 0AACED00

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

ho scritto tutti i blocchi di cattura separati di capire cosa eccezione era stato gettato e getta sempre l'InvalidClassException.

Anche qui è la mia classe Tree:

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

Ed ecco la mia scrittura al file funzioni:

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

La vostra conoscenza è apprezzato ...

traccia stack:

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) 

Processo terminato con codice di uscita 0

+1

Inviare anche uno stacktrace per favore. Questa è la migliore fonte per iniziare a individuare l'errore. –

+1

Cosa c'entra la classe 'Tree' con la fonte? – t0mm13b

+1

Questo è un programma? L'albero delle classi dovrebbe essere disponibile in classpath per poter deserializzare l'oggetto su di esso. – Rumoku

risposta

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

questo è causato aggiungendo al FileOutputStream. Come ho già detto in un commento in precedenza, non è possibile aggiungere a un flusso scritto da ObjectOutputStream, almeno non senza misure speciali. Tieni il file e il ObjectOutputStream aperto finché non hai scritto tutti gli oggetti che vuoi scrivere, quindi chiudilo e deserializzalo da esso.

NB Come Ho anche detto,

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

non è un ciclo oggetto lettura valida. readObject() non restituisce null alla fine del flusso: genera EOFException. null può verificarsi ovunque nello stream, ogni volta che ne scrivi uno.La forma corretta del ciclo è:

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

NB 2 Questo:

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

dovrebbe essere solo

oos.writeObject(object); 

In caso contrario si sta implicitamente chiamando toString() e inutilmente aggiungendo un terminatore di linea, quindi il risultato di readObject() sarà una stringa, non l'oggetto originale.

+0

Grazie @EJP. Quella risposta chiarisce molto di ciò che non stavo capendo! – Plewistopher

0

Penso che questo sia stato causato dalla mancanza di uno serialVersionUID.

Ogni volta che si serializza un oggetto, ClassLoader necessita di qualcosa per verificare il nuovo oggetto caricato per verificarlo e garantirne la compatibilità. Per fare questo, è sufficiente definire un campo nella classe in questo modo:

private static final long serialVersionUID = 12358903454875L; 

vostro IDE può avere anche dato un avviso che indica la mancanza di essa (Eclipse fa questo).

Questo dovrebbe risolvere il tuo problema.

Puoi trovare ulteriori informazioni in questa eccellente risposta di Jon Skeet qui: What is a serialVersionUID and why should I use it?.

+0

Sarebbe causato dalla mancanza di un 'serialVersionUID' * se * avesse eseguito la versione della classe. Non altrimenti. – EJP

+0

@EJP Ah, aspetta un secondo. Penso di aver mal interpretato la domanda ... – Zizouz212

+0

@EJP Sei sicuro? [Questo] (http://www.tutorialspoint.com/java/java_serialization.htm) articolo sembra supportare la mia teoria, almeno guardando brevemente al codice OPs, in quanto sembra che stia tentando di deserializzare un oggetto. Naturalmente, non so molto sulla serializzazione (e di solito non la uso), ma potrebbe essere il caso. – Zizouz212