68

I am going to write multiple objects to a file and then retrieve them in another part of my code. My code has no error, but it is not working properly. Could you please help me find what is wrong about my code. I read different codes from different websites, but none of them worked for me!

Here is my code to write my objects to a file: MyClassList is an arraylist which includes objects of my class (which must be written to a file).

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

I added "true" to the constructor of the outputstream, because I want to add each object to end of the file. Is that correct?

And here is my code to read the objects from the file:

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

It finally prints out just one object. Now, I don't know if I am not writing correctly or reading correctly!

4

5 回答 5

86

为什么不一次序列化整个列表?

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

当然,假设 MyClassList 是一个ArrayListorLinkedList或另一个Serializable集合。

在读回它的情况下,在您的代码中您只准备了一项,没有循环来收集所有写入的项。

于 2013-06-25T09:47:31.020 回答
54

正如其他人所建议的那样,您可以一次序列化和反序列化整个列表,这更简单,并且似乎完全符合您的意图。

在这种情况下,序列化代码变为

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 与资源一起使用,并且代码应该变得非常简单。

这是列表序列化:

try(
    FileOutputStream fout = new FileOutputStream("G:\\address.ser", true);
    ObjectOutputStream oos = new ObjectOutputStream(fout);
){
    oos.writeObject(myClassList);
} catch (Exception ex) {
    ex.printStackTrace();
}
于 2013-06-25T12:15:43.630 回答
3

将对象写入文件并从文件中读取对象的简单程序。

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 文件夹中找到该文件。

在此处输入图像描述

于 2018-12-14T18:20:19.897 回答
0

我认为你必须将每个对象写入一个自己的文件,或者你必须在读取它时拆分它。您也可以尝试序列化您的列表并在反序列化时检索它。

于 2013-06-25T09:50:05.377 回答
0

如果您序列化整个列表,则在读回文件时还必须将文件反序列化为列表。这意味着您将不可避免地在内存中加载一个大文件。它可能很昂贵。如果您有一个大文件,并且需要逐行(-> 逐个对象)将其分块,请继续您最初的想法

序列化:

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);
}
于 2018-05-23T10:53:43.153 回答