【问题标题】:Serialize multiple entries to the same file将多个条目序列化到同一个文件
【发布时间】:2016-11-23 06:49:45
【问题描述】:

我基本上是在制作一个日记应用程序,其中每个单独的日记条目都需要保留,我想将所有条目保存在一个文件中。

我看过很多关于序列化单个对象的教程,所以我想出了这个解决方案,(不起作用),但即使我设法修复它,感觉就像一个草率的解决方案。

(这里我尝试序列化一个arraylist,每次保存条目时,我都会反序列化列表并将新条目添加到列表中,然后再次序列化)

澄清一下,我的问题是:这是将对象多次保存到同一个文件的好方法吗?

或者是否有人对我应该尝试的其他事情有一些提示,也感谢指向视频或文档的链接。

public class Serializer 
{   

    //Calls readFile and adds the returned entries to an ArrayList
    //Add the target object to the list and write to the file
    public static void writeToFile(Object target)
    {   
        ArrayList entries = new ArrayList();

        entries = readFile();
        entries.add(target);


        String filename = "entries.bin";

        FileOutputStream fileOut = null;
        ObjectOutputStream objOut = null;

        try 
        {
            fileOut = new FileOutputStream(filename);
            objOut = new ObjectOutputStream(fileOut);
            objOut.writeObject(entries);
            objOut.close();
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
    }

    //Reads the file and returns all entries in a list
    public static ArrayList readFile () 
    {
        ArrayList persistedEntries = new ArrayList<>();
        String filename = "entries.bin"; 

        FileInputStream fileIn = null;
        ObjectInputStream objIn= null;
        try
        {
            fileIn = new FileInputStream(filename);
            objIn = new ObjectInputStream(fileIn);
            persistedEntries = (ArrayList) objIn.readObject();
            objIn.close();
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
        catch(ClassNotFoundException ex)
        {
            ex.printStackTrace();
        }

        return persistedEntries;
    }   
}

【问题讨论】:

  • 如果您还提到它“不起作用”的方式可能会有所帮助 - 它会引发异常吗?哪一个?
  • 我实际上并不确定什么不起作用,因为我得到了一个 Index out of range 异常,如果我理解 ArrayLists 不应该发生这种情况。但我只尝试运行程序,而不是方法本身。但是正如您所看到的,我的问题并不是关于代码不起作用的事实,我只是想看看“想法”是否好,或者我是否完全错过了一些东西并且应该朝另一个方向发展。 :)
  • 查看您的代码,我注意到您总是在 read 之前 writing 一个文件。必须检查空白文件entries.bin 的情况才能查看返回的 ArrayList 对象是什么?

标签: java serialization


【解决方案1】:

这是将对象多次保存到同一个文件的好方法吗?

我认为不。这是因为您的方法 writeToFile 或更准确地说是 appendToFile 可能会在极端情况下引入奇怪的行为(例如 entries.bin 有一个意外的对象)。我会为此辩护:

使用writeToFile(ArrayList&lt;Object&gt; target) 用指定的数组覆盖文件。然后添加一个方法appendToFile(Object target) 处理从磁盘读取entries.bin 的过程,附加target 然后将数组写入磁盘。这样做的好处是将与新对象target 与磁盘上的文件“合并”相关的任何逻辑与写入entries.bin 文件的实际逻辑分开。

如果只是一个学习练习,我会选择上述内容。潜力resource


添加重新格式化的版本:

public class Serializer 
{   
    private String filename;

    // pass in "entries.bin"
    public Serializer(String filename) {
        this.filename = filename;
    }

    public void append(Object target) {
        // readfile will return at least empty arraylist
        ArrayList entries = readFile();
        entries.add(target);
        serialize(entries);
    }

    public void serialize(ArrayList entries)
    {   
        FileOutputStream fileOut = null;
        ObjectOutputStream objOut = null;
        try 
        {
            fileOut = new FileOutputStream(filename);
            objOut = new ObjectOutputStream(fileOut);
            objOut.writeObject(entries);
            objOut.close();
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
    }

    //Reads the file and returns all entries in a list
    public ArrayList deserialize () 
    {
        ArrayList persistedEntries = new ArrayList<>();

        FileInputStream fileIn = null;
        ObjectInputStream objIn = null;
        try
        {
            fileIn = new FileInputStream(filename);
            objIn = new ObjectInputStream(fileIn);

            Object result = objIn.readObject();
            if (!(result instanceof ArrayList)) {
                // read object is not an arraylist
            }

            persistedEntries = (ArrayList) objIn.readObject();
            objIn.close();
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
        catch(ClassNotFoundException ex)
        {
            ex.printStackTrace();
        }

        return persistedEntries;
    }   
}

【讨论】:

  • 为什么?第二种方法完全等同于添加到列表中,然后调用第一种方法。两行代码。
  • 第二种方法是指appendToFile吗?正如我上面所说,它是关于分离逻辑和良好的编码实践。他目前正在使用writeToFile 的代码处理以下职责:在内存中构建数据,从源中读取数据,将源数据与内存中的数据同步,将数据写入源。以及与之相关的所有潜在错误和边缘情况。对他来说,将每个职责分成一个单独的方法更有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 2014-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多