2015-11-09 25 views
6

私はFile IOスキルを習得している学生ですが、ObjectInputStreamを使用してファイルからObjectを読み込む際に問題が発生しています。コードは一貫してInvalidClassExceptionをスローしているので、コードがオンラインまたは試行錯誤によってどのようにスローされているのかわかりません。ここに私のコードは次のとおりです。シリアライゼーション:java.io.StreamCorruptedException:無効なストリームヘッダー: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(); 
    } 
} 
} 

私は例外がスローされていた、それは常にによりInvalidClassExceptionを投げるかを把握するために別のcatchブロックのすべてを書きました。ここで

も私のツリークラスである:

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 Found\n"); 
     return false; 
    } catch (IOException e) { 
     System.out.print("IOException\n"); 
     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で処理が完了しました

+1

また、スタックトレースを投稿してください。それがエラーを特定するのに最適な情報源です。 –

+1

クラス 'Tree'はソースと何が関係していますか? – t0mm13b

+1

その1つのプログラムですか?オブジェクトへのオブジェクトの逆シリアル化ができるようにするには、クラスパスでクラスツリーを使用できるようにする必要があります。 – Rumoku

答えて

3
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()の結果は、元のオブジェクトではなくStringになります。

+0

ありがとうございます@EJP。その答えは私が理解していないことの多くをクリアします! – Plewistopher

0

これはserialVersionUIDがないために発生したと考えています。

オブジェクトをシリアル化するときはいつでも、ClassLoaderは新しい読み込み済みオブジェクトを検証して検証し、その互換性を保証する何かが必要です。これを行うためには、あなただけの、このようなあなたのクラスのフィールドを定義する必要があります。

private static final long serialVersionUID = 12358903454875L; 

あなたのIDEはまた、あなたのそれの欠如を(Eclipseがこれを行う)を示す警告を与えている可能性があります。

これは問題を解決するはずです。

ここでは、Jon Skeetの優れた回答をWhat is a serialVersionUID and why should I use it?で詳しく知ることができます。

+0

クラスをバージョン管理していた場合は、 'serialVersionUID' * if *が不足していることが原因です。そうでなければ。 – EJP

+0

@EJPああ、ちょっと待ってください。私は本当にひどく間違って質問を誤解したと思います... – Zizouz212

+0

@EJPよろしいですか? [this](http://www.tutorialspot.com/java/java_serialization.htm)の記事は、彼がオブジェクトをデシリアライズしようとしているように見えるので、私の理論をサポートしていると思われます。もちろん、シリアライゼーションについてはあまりよく分かりませんが(通常は使用しませんが)、そうかもしれません。 – Zizouz212

関連する問題