4

我正在开发一个大型 GUI 程序,其中我有很多项目数据需要locally按命令存储。

目前,我将所有全局数据结构保存在保存类(项目)中,然后将它们序列化到本地硬盘文件:

public void saveChanges() {
    ArrayList<Student> studentList = new ArrayList<>();
    ArrayList<String> coursesList = new ArrayList<>();
    ArrayList<Requirement> reqList = new ArrayList<>();
    ArrayList<Risk> riskList = new ArrayList<>();
    for (int x = 0; x < dlm.getSize(); x++) {
        studentList.add(dlm.elementAt(x));
    }
    for (int x = 0; x < dlm2.getSize(); x++) {
        coursesList.add(dlm2.elementAt(x));
    }
    for (int x = 0; x < dlm3.getSize(); x++) {
        reqList.add(dlm3.elementAt(x));
    }
    for (int x = 0; x < riskTable.getRowCount(); x++) {
        riskList.add((Risk) riskMap.get(dtm1.getValueAt(x, 0)));
    }

    project.setStudentAL(studentList);
    project.setCoursesAL(coursesList);
    project.setReqAL(reqList);
    project.setRiskAL(riskList);
    project.setLastUpdated(new Date().toString());

}

现在我将其序列化为本地文件:

public void saveProject(boolean defaultPath, String path) {
    saveChanges();
    FileOutputStream outFile;
    try {
        if (defaultPath) {
            outFile = new FileOutputStream(directory + project.getProjectName() +    ".proj");
        } else {
            outFile = new FileOutputStream(path + ".proj");
        }
        ObjectOutputStream outObject = new ObjectOutputStream(outFile);
        outObject.writeObject(project);
        outObject.close();
    } catch (IOException e) {
        System.out.println("Failed to save project");
        e.printStackTrace();
    }
}

我的问题是:有默认值吗?或更好的方法将文件保存在本地硬盘上?我不想使用 XML 或任何数据库。

  • 提前致谢
4

3 回答 3

2

在我看来,serialization这是很难在正确的地方使用的东西。
有时它被用作占位符,因为它的维护要求低且易于设置。然而,反对使用(自动)序列化作为灵丹妙药的观点(不要误会我的意思,序列化很有趣,而且在很多情况下它的使用是合适的)是:

  • 速度:标准 Java 序列化很慢。不一定,但如果在没有准备的情况下使用。解决方法:自己的writeObject/readObject方法。

  • 版本控制:当然,它注意不要反序列化太旧的东西(serialVersionUID),但它不能升级你的内部结构。如果你改变你在内部做事的方式,你的旧存档就没用了。

  • 二进制格式:您坚持使用标准 Java 序列化...您不能(没有变通方法)更改为另一种格式,也不能从另一种语言读取它...

一种选择

看起来您不想要数据库或 xml(我只是假设 JSON 也不可行)。所以,剩下的就是设计自己的格式并以二进制格式写入数据。这为您提供了最大的灵活性(尽管我并不是说它比文本格式更容易),并且如果应用正确,速度将比 Java 序列化或 xml 快得多。

然而,这些优势是有代价的:没有预先构建的系统(应该如何存在?)可以简单地做到这一点。您将不得不编写比 Java 序列化更多的代码,相信我,(大)结构化二进制文件可能会令人讨厌调试......

一个例子

假设您有一个名为 Data 的对象。它包含一个浮点数组。在 writeObject 上,您写入该数组的大小,然后将每个浮点数写入流中。
在 readObject 上,您读取数组的大小,创建该大小的数组并用读取的浮点数填充数组中的每个元素。

于 2013-08-27T17:58:23.477 回答
2

我在提出实际建议时遇到了麻烦,因为我不太了解您为什么不考虑 XML 或嵌入式数据库。但这里有一些事情需要考虑。

  • 版本控制。如果您需要向其中一个对象添加一个字段,但您已经保存了一些没有该字段的文件怎么办?根据您用于保存状态的技术,这可能是巨大的痛苦或中度的痛苦。我认为 java 对象序列化不容易处理这个问题。

  • 对象身份。在上面的代码片段中,项目由其名称标识,该名称也可以作为人类友好的标识符。一般来说,最好有一个“无意义”的属性用于标识。通过这种方式,您可以更改项目的名称并使其仍然是“相同”的对象。您还必须担心冲突,因为 2 个不同的对象具有相同的标识,特别是如果它是用户指定的属性。

现在这里有一些您可能会考虑的其他存储格式,同样不知道您的限制。

  • JSON。Jackson 序列化库非常适合以 JSON 格式保存/加载 java 对象。如果你有“java bean”风格的对象,它很容易使用。一个不错的功能是您可以对其进行配置,以便在读取旧对象时新对象属性不会引起问题。

  • 二进制,例如协议缓冲区。这些比 JSON 更快,但不那么容易使用。它可以毫无问题地处理其他字段。

于 2013-08-27T18:35:24.573 回答
2

对于 swing 应用程序,我真的很喜欢使用 XML。这具有使您保存的数据可能对其他应用程序有用的额外好处。JAXP提供了在您的程序中写入和读取 XML 数据的方法——您需要做的就是编写一些代码来保持并重新创建您正在保存的状态。

如果您正在写入大量数据(听起来像是),我建议使用 SAX 接口将其读入您的应用程序。这里有一个关于这样做的教程。

另一种存储数据的方法是使用数据库。使用Apache Derby之类的东西也是一种选择。

于 2013-08-27T16:52:50.310 回答