Java对象序列化,与ObjectOutPutStream一起使用后如何使用相同的文件

Posted

技术标签:

【中文标题】Java对象序列化,与ObjectOutPutStream一起使用后如何使用相同的文件【英文标题】:Java object serialization, how to use same file after using it with ObjectOutPutStream 【发布时间】:2015-08-13 04:50:04 【问题描述】:

我想将一个简单的 Person 类(带有姓名和年龄)序列化到一个名为“somepersons.ser”的文件中。基本上我想实现以下代码的行为:

        Person p1 = new Person("Person1", 45);
        Person p2 = new Person("Person2", 35);

        FileOutputStream fos = new FileOutputStream("somepersons.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(p1);
        oos.writeObject(p2);
        oos.close();

        FileInputStream fis = new FileInputStream("somepersons.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        p1 = (Person)ois.readObject();
        p2 = (Person)ois.readObject();
        System.out.println(p1);
        System.out.println(p2);

此代码将两个 Person 存储在一个文件中,然后将它们恢复并显示在屏幕上。这按预期工作。

我的问题是:我想将存储 Person 的代码放在一个单独的方法中,因此您可以使用文件路径名和要序列化的 Person 作为参数调用该方法,然后该方法序列化传递的人到文件中。基本上我希望代码能够做这样的事情:

        Person p1 = new Person("Person1", 45);
        Person p2 = new Person("Person2", 35);

        FileOutputStream fos = new FileOutputStream("somepersons.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(p1);
        oos.close();

        FileOutputStream fos2 = new FileOutputStream("somepersons.ser");
        ObjectOutputStream oos2 = new ObjectOutputStream(fos2);
        oos2.writeObject(p2);
        oos2.close();

        FileInputStream fis = new FileInputStream("somepersons.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        p1 = (Persona)ois.readObject();
        p2 = (Persona)ois.readObject();
        System.out.println(p1);            
        System.out.println(p2);

第二段代码尝试与第一段代码相同,但不依赖已创建的 FileOutputStream 及其对应的 ObjectOutputStream 的存在。 但是当我第二次尝试在 ObjectInputStream ois 上调用 readObject 时,它会引发 EOFException,因为只有一个对象已被序列化(第二个 Person)。我尝试过刷新、重置等,但我得到了一个不同的异常,但它总是失败。 我怀疑在这段代码中存在一些我不太理解的重要序列化概念,我希望有人能帮我解释一下。我见过类似的问题,但答案似乎不适合我的问题。如果我不想同时序列化所有对象,如何实现第一段代码的行为?更重要的是(提高我对序列化的理解),为什么这不起作用? 谢谢!

【问题讨论】:

对象序列化对于对象的长期存储来说是一个糟糕的选择,考虑使用更像JAXB 的东西。提示FileOutputStream(File, boolean) 你考虑过写两个文件吗? 【参考方案1】:

要按照您想要的方式进行操作,您需要使用自定义类扩展 ObjectOutputStream 并覆盖 writeStreamHeader 方法。

您需要找到一种方法来知道您是否是第一次写入流(例如使用历史文件:如果历史文件尚不存在,则为第一次,否则您已经写入流)。当您第一次使用原始 ObjectOutputStream 写入流时,您还创建了历史文件。

当您下次写入时,历史文件的存在让您知道这不是第一次,因此您使用自定义 ObjectOutputStream 类的实例并使用它写入流。它不会写入标题,但会调用重置。查看更多here

【讨论】:

以上是关于Java对象序列化,与ObjectOutPutStream一起使用后如何使用相同的文件的主要内容,如果未能解决你的问题,请参考以下文章

java 对象序列化与反序列化

java 对象序列化与反序列化

java对象的序列化与反序列化

java对象序列化与反序列化

Java序列化与对象流浅谈

Java序列化与反序列化