【问题标题】:Deserializing multiple objects from a single file [duplicate]从单个文件反序列化多个对象[重复]
【发布时间】:2011-12-04 23:07:59
【问题描述】:

我有许多对象(同一类)序列化到一个文件中。 但是在反序列化的时候,只有第一个序列化的对象会被反序列化。

序列化代码:

public void save() {
File f = new File("vehicule.txt");
try {
    if(!f.exists()) f.createNewFile();
} catch(IOException e) {
}
try {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f,true));
oos.writeObject(this);
} catch(IOException e) {
}

}

我认为问题出在:

Vehicule v;
while( (v = (Vehicule)ois.readObject()) != null )

有没有更好的方法来检查文件的结尾?

【问题讨论】:

  • 您能说明如何将对象序列化到文件中吗?看起来您正在执行自定义序列化过程。
  • 你不说你的问题到底是什么,看看你是如何捕获然后丢弃异常的,你不太可能说它是什么。
  • ObjectOutputStream 不生成文本文件。它是二进制的。

标签: java deserialization


【解决方案1】:

最好在开头写下文件中的车辆数量,然后让它控制你读取的数量。

如果您想按照自己的方式进行操作,那么您将不得不尝试/捕获 IOException

[顺便说一句,这不是 txt 文件]

【讨论】:

  • 使用反序列化对象的数量没有帮助。只打印第一个对象
  • 或者序列化一个List
【解决方案2】:

如果您要使用多个附加的ObjectOutputStreams,那么我相信this 可能会有所帮助(同时确保每次运行测试时都删除该文件!):

为什么一个包含多个附加 ObjectOutputStream 的文件不能被一个 ObjectInputStream 反序列化?

使用序列化的默认实现,必须有一个 ObjectOutputStream 构造与 ObjectInputStream 建设。 ObjectOutputStream构造函数 写入一个流头,ObjectInputStream 读取这个流 标题。一种解决方法是继承ObjectOutputStream 并覆盖 writeStreamHeader()。压倒一切的writeStreamHeader() 应该 如果是第一次写入,则调用 super writeStreamHeader 方法 该文件,如果是,它应该调用ObjectOutputStream.reset() 附加到文件中预先存在的ObjectOutputStream

否则我建议您将对象添加到List,然后使用单个ObjectOutputStream 对其进行序列化。

例如:

    Vehicule v1 = new Vehicule();
    Vehicule v2 = new Vehicule();
    List<Vehicule> vehicules = Arrays.asList(v1, v2);

    // serialize the list of Vehicules
    File f = new File("vehicule.txt");
    try {
        ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(f));
        oos.writeObject(vehicules);
        oos.close();
    } catch (Exception e) {
        e.printStackTrace(); // handle this appropriately
    }

    // deserialize the list of Vehicules
    try {
        ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(f));
        List<Vehicule> deserializedVehicles = (List<Vehicule>) ois.readObject();
        ois.close();
        System.out.println("list size = " + deserializedVehicles.size());
    } catch (Exception e) {
        e.printStackTrace(); // handle this appropriately
    }

对我来说,这个输出:

list size = 2

【讨论】:

  • 我用 ArrayList 试过了。也没有用
  • 现在您已经添加了序列化代码,在我看来您已经在 Vehicule 类 (oos.writeObject(this);) 上实现了 save() 方法。要序列化为列表,您必须序列化该类之外的所有车辆(在一个方法调用中)。
  • @NiceBooks 定义“没用”。
  • 您是否尝试仅使用 1 个 ObjectOutputStream(即不附加到现有文件)和一个列表进行序列化?
  • 是的,这就是重点。您必须一次性进行序列化 - 如果您不这样做,那么您将无法对其进行反序列化(因为一个文件中会有多个标题)。如果要保留以前的车辆,则每次创建一个新文件。
【解决方案3】:
try {
    if(!f.exists()) f.createNewFile();
} catch(IOException e) {
}

你不需要这些。 new FileOutputStream() 将创建文件。

new ObjectOutputStream(new FileOutputStream(f,true))

您不能附加到ObjectOutputStream。如果ObjectInputStream 在流中间遇到它们,则其中有一些标题。

while( (v = (Vehicule)ois.readObject()) != null )

有没有更好的方法来检查文件的结尾?

Javadoc 中没有关于 readobject() 在 EOS 返回 null 的内容。 readObject() 返回 null 当且仅当您写了 null

正确的技术是捕获EOFException,关闭流,然后跳出循环。

【讨论】:

    【解决方案4】:

    只需序列化/反序列化 ArrayList&lt;Vehicle&gt;(而不是尝试将多个对象填充到单个文件中)。

    【讨论】:

      【解决方案5】:

      好的,这就是它最终的工作方式。
      我将文件中的所有内容反序列化为 ArrayList;添加了新对象并在序列化时,我将 ArrayList 的每个元素添加到文件中[使用 (new FileOutputStream(new File("Vehicule.txt"),false) 擦除以前的条目]。
      最后,我在文件中显式添加了一个空值,以帮助反序列化。
      同样在第一次使用 createNewFile 创建文件时,我在文件中添加了一个空值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-01
        相关资源
        最近更新 更多