ArrayList上的Serializable丢失了一些数据

问题描述 投票:1回答:3

我有一个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);
}

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

edit1:如果我一次添加所有元素一切都很好但不是我先做的方式。有什么不同?

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个元素

java serializable
3个回答
1
投票

由于GhostCat和uaraven已经提到重置不是你期望它做的,你应该看一下序列化的教程,也许可以考虑使用......否则,如果这不适合您的用例。

如果创建新的FileOutputStream,您的代码可能如下所示:

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class SerializationTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        String path = "EmpObject.ser";

        ArrayList<Employee> empList = new ArrayList<>();
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));

        empList.add(emp1);
        empList.add(emp2);
        oos.writeObject(empList);

        empList.add(emp3);
        // Create a new FileOutputStream to override the files content instead of appending the new employee list
        oos = new ObjectOutputStream( new FileOutputStream(path));
        oos.writeObject(empList);

        ObjectInputStream objectinputstream = new ObjectInputStream(new FileInputStream(path));
        List<Employee> readCase = (List<Employee>) objectinputstream.readObject();

        System.out.println(readCase);
    }
}

2
投票

您的代码会发生什么:

  • 您将列表写入文件,有两个条目
  • 你重置了流
  • 你再次写下列表,有三个条目

因此,您的文件包含两个值,是的。两个列表,一个有2个,一个有3个条目。

换句话说:reset()不会重置已写入文件的内容!你写了一个包含两个条目的列表。您只是重置有关存储对象的信息,以便emp1和emp2再次完全序列化。如果没有重置调用,JVM会理解它不需要再次完全序列化emp1和emp2。

含义:默认情况下,JVM会压缩要传输的数据量。它会记住哪些对象已经写入,而不是重复写入,它只会将类似“之前序列化的对象X”的内容写入流中。

所以:我认为你根本不明白reset()方法的要点。解决方案:阅读一个小教程,就像来自tutorialspoint的教程一样。

根据OP的最新评论编辑:

你不能以这种方式提出要求。您正在编写列表对象。这意味着该列表中的所有条目都将写入该文件。 JVM记得“该列表已经写入”,因此即使其内部状态在此期间发生变化,它也不会再次写入。


1
投票

基本上ObjectOutputStream记得写入它的对象。如果再次写入相同的对象(通过引用),则不会将其序列化,而是将对先前序列化数据的引用写入流。 reset()方法清理ObjectOutputStream的内部数据结构,并允许您再次编写同一个对象。 reset()不会丢弃已写入流的数据。

如果您尝试将流反序列化为两个ArrayLists,您将获得一个包含两个元素和一个包含三个元素的元素。

如果你删除对reset()方法的调用,那么你将获得两个包含两个元素的数组列表(一个实际是序列化的,另一个是对前一个序列化实例的引用)

© www.soinside.com 2019 - 2024. All rights reserved.