猿问

ArrayList 上的可序列化丢失一些数据

我有一个 Employee 对象的 ArrayList,其中 Employee 类实现了 Serializable。我正在使用此代码将列表写入文件:


ArrayList<Employee> empList = new ArrayList<>();

  FileOutputStream fos = new FileOutputStream("EmpObject.ser");

  ObjectOutputStream oos = new ObjectOutputStream(fos);

  // write object to file

  empList .add(emp1);

  empList .add(emp2);

  oos.writeObject(empList);


  empList .add(emp3);


  oos.writeObject(empList);

}

如果我尝试反序列化它,我只会得到前两个对象而不是第三个对象。任何人都可以试试这是为什么?


编辑1:如果我一次添加所有元素,一切都很好,但不是我第一次做的方式。有什么区别?


ArrayList<Employee> empList = new ArrayList<>();

  FileOutputStream fos = new FileOutputStream("EmpObject.ser");

  ObjectOutputStream oos = new ObjectOutputStream(fos);

  // write object to file

  empList .add(emp1);

  empList .add(emp2);

  empList .add(emp3);

  oos.writeObject(empList);

}

在此之后我有 3 个元素


杨魅力
浏览 195回答 3
3回答

炎炎设计

基本上ObjectOutputStream记住写入它的对象。如果再次写入相同的对象(通过引用),它不会被序列化,而是对先前序列化数据的引用被写入流。reset()方法清理内部数据结构ObjectOutputStream并允许您再次编写相同的对象。reset()不会丢弃已写入流的数据。如果您尝试将流反序列化为两个 ArrayList,您将得到一个包含两个元素和一个包含三个元素。如果您删除对reset()方法的调用,那么您将获得两个包含两个元素的数组列表(一个实际序列化,另一个作为对先前序列化实例的引用)

Helenr

正如 GhostCat 和 uaraven 已经提到的那样,reset 并不是你期望的那样,你应该看看关于序列化的教程,也许考虑使用 sth。否则,如果这不适合您的用例。如果创建一个新的 FileOutputStream,您的代码可能如下所示:import java.io.*;import java.util.ArrayList;import java.util.List;public class SerializationTest {&nbsp; &nbsp; public static void main(String[] args) throws IOException, ClassNotFoundException {&nbsp; &nbsp; &nbsp; &nbsp; String path = "EmpObject.ser";&nbsp; &nbsp; &nbsp; &nbsp; ArrayList<Employee> empList = new ArrayList<>();&nbsp; &nbsp; &nbsp; &nbsp; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));&nbsp; &nbsp; &nbsp; &nbsp; empList.add(emp1);&nbsp; &nbsp; &nbsp; &nbsp; empList.add(emp2);&nbsp; &nbsp; &nbsp; &nbsp; oos.writeObject(empList);&nbsp; &nbsp; &nbsp; &nbsp; empList.add(emp3);&nbsp; &nbsp; &nbsp; &nbsp; // Create a new FileOutputStream to override the files content instead of appending the new employee list&nbsp; &nbsp; &nbsp; &nbsp; oos = new ObjectOutputStream( new FileOutputStream(path));&nbsp; &nbsp; &nbsp; &nbsp; oos.writeObject(empList);&nbsp; &nbsp; &nbsp; &nbsp; ObjectInputStream objectinputstream = new ObjectInputStream(new FileInputStream(path));&nbsp; &nbsp; &nbsp; &nbsp; List<Employee> readCase = (List<Employee>) objectinputstream.readObject();&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(readCase);&nbsp; &nbsp; }}

慕哥9229398

您的代码会发生什么:您将列表写入文件,其中包含两个条目你重置了流你再写一次清单,三个条目因此,您的文件包含两个值,是的。两个列表,一个有 2 个,一个有 3 个条目。换句话说:reset()不会重置已写入文件的内容!你写了一个包含两个条目的列表。您只是重置有关存储对象的信息,以便 emp1 和 emp2再次完全序列化。如果不调用 reset,JVM 就会明白它不需要再次完全序列化 emp1 和 emp2。含义:默认情况下,JVM 会压缩要传输的数据量。它会记住哪些对象已经写入,而不是重复写入它们,它只会将“之前序列化的对象 X 再次出现”之类的内容写入流中。所以:我认为您根本不了解该reset()方法的要点。解决方案:阅读一个小教程,比如来自tutorialspoint的教程。根据 OP 的最新评论进行编辑:你要求的东西是不可能的。您正在编写列表对象。这意味着此时该列表的所有条目都会写入文件。JVM 会记住“该列表已被写入”,因此即使其内部状态同时发生变化,它也不会再次写入。
随时随地看视频慕课网APP

相关分类

Java
我要回答