2016-04-13 5 views
1

Ich bin neugierig, warum ich this zu einem ObjectOutputStream nicht erfolgreich schreiben kann.Warum kann ich das nicht in Java serialisieren

Ich habe die folgende Klasse geschrieben und fand es mit allen notwendigen Importe funktionieren:

public class Cereal implements Serializable{ 

    private String name ; 
    private FileInputStream fis ; 
    private ObjectInputStream ois ; 
    private ObjectOutputStream oos; 
    private FileOutputStream fos ; 
    private Cereal readIn ; 
    private Cereal writeOut; 

    private Toy prize ; 
    public Cereal(String newName, String prizeName){ 
     name = newName ; 
    } 
    public String readBox(){ 
     return name ; 
    } 
    //Where it happens; unsuccessful line commented out 
    public void writeToFile(String arg) throws Exception{ 
     try{ 
      fos = new FileOutputStream(arg) ; 
      oos = new ObjectOutputStream(fos) ; 
      writeOut = new Cereal(name, prize.describe()); 
      oos.writeObject(writeOut); 
      //oos.writeObject(this); 
      oos.close(); 
      fos.close(); 
      System.out.println("wrote to " + arg); 

     }catch(Exception e){ 
      System.out.println("Problem"); 
      e.printStackTrace(); 
     } 

    } 
    public void writeToFile() throws Exception{ 
     // 
     writeToFile(name + ".ser") ; 
    } 
    public void readFromFile(String arg) throws Exception{ 

     try{ 
      fis = new FileInputStream(arg) ; 
      ois = new ObjectInputStream(fis) ; 

      System.out.println("Read from " + arg); 
      readIn = (Cereal) ois.readObject() ; 
      this.name = readIn.readBox(); 
      ois.close(); 
      fis.close(); 

     }catch(Exception e){ 
      System.out.println("Had a problem"); 
      e.printStackTrace(); 
     } 
    } 
    public void readFromFile() throws Exception{ 
     readFromFile(name + ".ser"); 
    } 


} 

Doch oos.writeObject(writeOut) mit oos.writeObject(this) ersetzen, ich hebe die folgenden Fehler:

java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: java.io.FileOutputStream 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1355) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) 
    at Cereal.readFromFile(Cereal.java:56) 
    at MainDriver.main(MainDriver.java:13) 
Caused by: java.io.NotSerializableException: java.io.FileOutputStream 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) 
    at Cereal.writeToFile(Cereal.java:34) 
    at Cereal.writeToFile(Cereal.java:47) 
    at MainDriver.main(MainDriver.java:7) 

Ich bin nicht sicher, warum das ein Problem sein sollte, hat jemand eine Idee? Danke im Voraus. (Es scheint umständlich ein Attribut eher zu initialisieren als nur this benutzen, wie ich es jetzt tue.)

+1

die FileInput- und Ausgabeströme werden geöffnet und in den Schutzbereich des Verfahrens geschlossen. Sie sollten lokale Variablen sein. – slipperyseal

Antwort

3

Unter der Annahme, Toy ist auch Serializable, müssen Sie Ihre Streams machen transient (weil sie sind nichtSerializable). So etwas wie,

private transient FileInputStream fis ; 
private transient ObjectInputStream ois ; 
private transient ObjectOutputStream oos; 
private transient FileOutputStream fos ; 

Deshalb ist die Wurzel Ihrer Stack-Trace sagt

Caused by: java.io.NotSerializableException: java.io.FileOutputStream 

Sie auch diese Ströme lokale Variablen anstelle von Feldern machen könnte, und verwenden Sie try-with-resources Close aufzuräumen. Etwas wie

public void readFromFile(String arg) throws Exception { 
    try (ObjectInputStream ois = new ObjectInputStream(
       new FileInputStream(arg))) { 
     System.out.println("Read from " + arg); 
     readIn = (Cereal) ois.readObject(); 
     this.name = readIn.readBox(); 
    } catch (Exception e) { 
     System.out.println("Had a problem"); 
     e.printStackTrace(); 
    } 
} 

und

public void writeToFile(String arg) throws Exception { 
    try (ObjectOutputStream oos = new ObjectOutputStream(
       new FileOutputStream(arg))) { 
     writeOut = new Cereal(name, prize.describe()); 
     oos.writeObject(writeOut); 
     System.out.println("wrote to " + arg); 
    } catch (Exception e) { 
     System.out.println("Problem"); 
     e.printStackTrace(); 
    } 
} 
+1

Oder machen Sie sie nur lokale Variablen, weil sie nur für die Lebensdauer der Methodenaufrufe verwendet werden. Felder scheinen hier keinen Zweck zu erfüllen. Das gleiche gilt für 'readIn' und' writeOut'. Sie sollten lokale Variablen sein. – Radiodef

+1

Und ['try-with-resources'] (http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) würde es sauberer machen. –

+0

Das wird es tun, die Streams vorübergehend zu beheben. Danke vielmals. (SO braucht ein paar Minuten, um mich die Antwort akzeptieren zu lassen, denke darüber nach.) – Garrett