保存项目数据。你会怎么做? [关闭]

Posted

技术标签:

【中文标题】保存项目数据。你会怎么做? [关闭]【英文标题】:Saving project data. How would you do it? [closed] 【发布时间】:2013-08-30 13:05:51 【问题描述】:

我正在开发一个大型 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 或任何 DB。

提前致谢

【问题讨论】:

为了阻止与您的需求不符的建议,详细说明您不想使用 XML 或数据库的原因可能会很有用。这是个人偏好吗,在这种情况下,一个好的论据可以说服你吗?还是出于某种原因项目的硬性要求? 【参考方案1】:

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

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

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

【讨论】:

XML 是不可能的,sry 应该把它添加到问题中 一个类似这样的问题的抬头 - 人们对他们如何存储状态有自己的偏好。如果您正在做的事情对您有用并且性能可以接受,那么这是一种正确的方法。以其他方式这样做有一些优势,但它们可能与您的情况无关。 作为您最新编辑的附加评论。我将其开发为与使用 mysql 等数据库完全相反。它必须存储在本地。 Derby 的优点之一是它允许您以本地方式使用它。这里的tutorial 介绍了嵌入模式。这基本上允许您以符合您要求的方式使用 Derby。 @Surveon 那不是我要找的东西【参考方案2】:

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

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

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

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

李>

另一种选择

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

然而,这些优势是有代价的:没有预先构建的系统(应该如何存在?),它只是它。与 Java 序列化相比,您必须编写更多代码,相信我,(大)结构化二进制文件调试起来可能很烦人......

一个例子

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

【讨论】:

【参考方案3】:

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

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

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

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

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

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

【讨论】:

以上是关于保存项目数据。你会怎么做? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

项目经理面试题

你会用哪种语言自学SICP? [关闭]

我想要第一个 ExpansionTile 的项目默认是打开的。我想当我单击另一个项目时,当前项目将关闭。我该怎么做?

keiluvision5如何显示项目代码

我正在尝试将图像路径数据库和图像本身保存到项目中的文件夹[关闭]

Laravel 多对多关系在哪里保存项目总数? [关闭]