web-dev-qa-db-ja.com

Javaシリアル化されたオブジェクトをファイルに読み書きする方法

複数のオブジェクトをファイルに書き込み、コードの別の部分でそれらを取得します。私のコードにはエラーはありませんが、正しく機能していません。私のコードの何が問題なのかを見つけてください。私は異なるウェブサイトから異なるコードを読みましたが、それらのどれも私のために働きませんでした!

オブジェクトをファイルに書き込むためのコードを次に示します。MyClassListは、クラスのオブジェクト(ファイルに書き込む必要がある)を含む配列リストです。

for (int cnt = 0; cnt < MyClassList.size(); cnt++) {
    FileOutputStream fout = new FileOutputStream("G:\\address.ser", true);
    ObjectOutputStream oos = new ObjectOutputStream(fout);
    oos.writeObject(MyClassList.get(cnt));
}

各オブジェクトをファイルの終わりに追加したいので、出力ストリームのコンストラクターに「true」を追加しました。あれは正しいですか?

そして、ファイルからオブジェクトを読み取るための私のコードは次のとおりです。

 try {
     streamIn = new FileInputStream("G:\\address.ser");
     ObjectInputStream objectinputstream = new ObjectInputStream(streamIn);
     MyClass readCase = (MyClass) objectinputstream.readObject();
     recordList.add(readCase);
     System.out.println(recordList.get(i));
 } catch (Exception e) {
     e.printStackTrace();
 }

最終的に1つのオブジェクトのみを出力します。今、私は正しく書いていないのか、正しく読んでいないのかわかりません!

51
user1419243

リスト全体を一度にシリアル化しないのはなぜですか?

FileOutputStream fout = new FileOutputStream("G:\\address.ser");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(MyClassList);

もちろん、MyClassListがArrayListまたはLinkedList、または別のSerializableコレクションであると仮定します。

それを読み返す場合、コードには1つのアイテムのみを用意し、書き込まれたすべてのアイテムを収集するループはありません。

70
forty-two

他の人が示唆したように、リスト全体を一度にシリアライズおよびデシリアライズすることができます。これは、より簡単で、目的に完全に準拠しているようです。

その場合、シリアル化コードは次のようになります

ObjectOutputStream oos = null;
FileOutputStream fout = null;
try{
    fout = new FileOutputStream("G:\\address.ser", true);
    oos = new ObjectOutputStream(fout);
    oos.writeObject(myClassList);
} catch (Exception ex) {
    ex.printStackTrace();
} finally {
    if(oos != null){
        oos.close();
    } 
}

そして、逆シリアル化が行われます(myClassListがリストであると仮定し、ジェネリックを使用することを望んでいます):

ObjectInputStream objectinputstream = null;
try {
    FileInputStream streamIn = new FileInputStream("G:\\address.ser");
    objectinputstream = new ObjectInputStream(streamIn);
    List<MyClass> readCase = (List<MyClass>) objectinputstream.readObject();
    recordList.add(readCase);
    System.out.println(recordList.get(i));
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if(objectinputstream != null){
        objectinputstream .close();
    } 
}

次の目的で、ファイルから複数のオブジェクトをデシリアライズすることもできます。

ObjectInputStream objectinputstream = null;
try {
    streamIn = new FileInputStream("G:\\address.ser");
    objectinputstream = new ObjectInputStream(streamIn);
    MyClass readCase = null;
    do {
        readCase = (MyClass) objectinputstream.readObject();
        if(readCase != null){
            recordList.add(readCase);
        } 
    } while (readCase != null)        
    System.out.println(recordList.get(i));
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if(objectinputstream != null){
        objectinputstream .close();
    } 
}

Finally節でストリームオブジェクトを閉じることを忘れないでください(注:例外をスローする可能性があります)。

編集

コメントで示唆されているように、 リソースで試してみてください を使用することをお勧めします。コードは非常にシンプルになります。

リストのシリアル化は次のとおりです。

try(
    FileOutputStream fout = new FileOutputStream("G:\\address.ser", true);
    ObjectOutputStream oos = new ObjectOutputStream(fout);
){
    oos.writeObject(myClassList);
} catch (Exception ex) {
    ex.printStackTrace();
}
44
C.Champagne

オブジェクトをファイルに書き込み、ファイルからオブジェクトを読み取るための単純なプログラム。

package program;

import Java.io.File;
import Java.io.FileInputStream;
import Java.io.FileOutputStream;
import Java.io.ObjectInputStream;
import Java.io.ObjectOutputStream;
import Java.io.Serializable;

public class TempList {

  public static void main(String[] args) throws Exception {
    Counter counter = new Counter(10);

    File f = new File("MyFile.txt");
    FileOutputStream fos = new FileOutputStream(f);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(counter);
    oos.close();

    FileInputStream fis = new FileInputStream(f);
    ObjectInputStream ois = new ObjectInputStream(fis);
    Counter newCounter = (Counter) ois.readObject();
    System.out.println(newCounter.count);
    ois.close();
  }

}

class Counter implements Serializable {

  private static final long serialVersionUID = -628789568975888036 L;

  int count;

  Counter(int count) {
    this.count = count;
  }
}

プログラムを実行すると、コンソールウィンドウの出力は10になります。下の画像にあるアイコンをクリックして、Testフォルダー内のファイルを見つけることができます。

enter image description here

1
Roshan Halwai

リスト全体をシリアル化する場合は、読み戻すときにファイルをリストに逆シリアル化する必要もあります。これは、必然的に大きなファイルをメモリにロードすることを意味します。高価な場合があります。大きなファイルがあり、1行ずつ(->オブジェクトごとに)チャンクする必要がある場合は、単に最初のアイデアで進めてくださいです。

シリアル化:

LinkedList<YourObject> listOfObjects = <something>;
try {
    FileOutputStream file = new FileOutputStream(<filePath>);
    ObjectOutputStream writer = new ObjectOutputStream(file);
    for (YourObject obj : listOfObjects) {
        writer.writeObject(obj);
    }
    writer.close();
    file.close();
} catch (Exception ex) {
    System.err.println("failed to write " + filePath + ", "+ ex);
}

逆シリアル化:

try {
    FileInputStream file = new FileInputStream(<filePath>);
    ObjectInputStream reader = new ObjectInputStream(file);
    while (true) {
        try { 
            YourObject obj = (YourObject)reader.readObject();
            System.out.println(obj)
        } catch (Exception ex) {
            System.err.println("end of reader file ");
            break;
        }
    }
} catch (Exception ex) {
    System.err.println("failed to read " + filePath + ", "+ ex);
}
0
angelo.mastro

各オブジェクトを独自のファイルに書き込む必要があるか、読み込むときにオブジェクトを分割する必要があると思います。リストをシリアル化して、逆シリアル化するときにリストを取得することもできます。

0
Sammy