我有一个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个元素
由于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个,一个有3个条目。
换句话说:reset()
不会重置已写入文件的内容!你写了一个包含两个条目的列表。您只是重置有关存储对象的信息,以便emp1和emp2再次完全序列化。如果没有重置调用,JVM会理解它不需要再次完全序列化emp1和emp2。
含义:默认情况下,JVM会压缩要传输的数据量。它会记住哪些对象已经写入,而不是重复写入,它只会将类似“之前序列化的对象X”的内容写入流中。
所以:我认为你根本不明白reset()
方法的要点。解决方案:阅读一个小教程,就像来自tutorialspoint的教程一样。
根据OP的最新评论编辑:
你不能以这种方式提出要求。您正在编写列表对象。这意味着该列表中的所有条目都将写入该文件。 JVM记得“该列表已经写入”,因此即使其内部状态在此期间发生变化,它也不会再次写入。
基本上ObjectOutputStream
记得写入它的对象。如果再次写入相同的对象(通过引用),则不会将其序列化,而是将对先前序列化数据的引用写入流。 reset()
方法清理ObjectOutputStream
的内部数据结构,并允许您再次编写同一个对象。 reset()
不会丢弃已写入流的数据。
如果您尝试将流反序列化为两个ArrayLists,您将获得一个包含两个元素和一个包含三个元素的元素。
如果你删除对reset()
方法的调用,那么你将获得两个包含两个元素的数组列表(一个实际是序列化的,另一个是对前一个序列化实例的引用)