Java: 从磁盘读/写一个Map

15

我有一个数据结构,希望能在关闭程序之前将其写入文件,并且下次启动应用程序时从文件中读取以重新填充结构。

我的结构是HashMap<String, Object>。Object 很简单; 对于成员变量,它有一个字符串和两个小的本地布尔类型数组。这是一个非常简单的应用程序,一次不会超过10-15个<键,值>对。

我一直在使用对象输入/输出流进行实验(但没有成功)。我需要将 Object 类设置为 Serializable 吗?

您能为我提供任何关于如何最好地做到这一点的建议吗?我只需要在正确的方向上获得一些推动,谢谢!

编辑:好吧,我觉得自己很蠢,我正在从一个 map 写入并读取到另一个 map,然后比较它们以检查我的结果。显然,我比较它们的方式是错误的。唉。


1
HashMap已经实现了Serializable接口。当您尝试将其写入ObjectOutputStream时出了什么问题? - finnw
对象输入/输出流不是唯一的选择。您是想要关于使用它们的建议吗?还是关于I/O的一般性建议? - Raedwald
@Raedwald - 我只是在寻找一个简单应用程序的最佳方法。谷歌引导我使用对象流。 - jazz99
@finnw - 我是根据在网上找到的示例编写的代码,但它们都是<String,String>示例,而我正在处理<String,Object>。我的Object类是可序列化的,但我不确定我是否正确地实现了它。这是第一次! - jazz99
2017年有一个很有趣的库:http://www.mapdb.org/ - Sridhar Sarnobat
7个回答

35

如果你不特别关心对象,只需要一对键值为String,String的话,我建议您使用java.util.Properties。否则可以选择以下内容。

        Map map = new HashMap();
        map.put("1",new Integer(1));
        map.put("2",new Integer(2));
        map.put("3",new Integer(3));
        FileOutputStream fos = new FileOutputStream("map.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(map);
        oos.close();

        FileInputStream fis = new FileInputStream("map.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Map anotherMap = (Map) ois.readObject();
        ois.close();

        System.out.println(anotherMap);

1
我肯定没有使用.ser扩展名,会尝试一下。谢谢。 - jazz99
8
“.ser” 不应该是核心问题,你可以在这里给任何扩展名,或者在这里不使用任何扩展名也可以。 - jmj
3
是的,对于Java来说,".ser"扩展名没有实际意义。 - Jé Queue
@JigarJoshi 你不需要关闭两个流吗?fos.close(); 和 fis.close();?或者关闭对象流会同时关闭文件流吗? - HpTerm
你是真正的MVP Joshi!谢谢! - Sipty
显示剩余2条评论

2
Map m = new HashMap();
// let's use untyped and autoboxing just for example
m.put("One",1);
m.put("Two",2);

ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("foo.ser")
);
oos.writeObject(m);
oos.flush();
oos.close();

2
是的,你的对象需要实现Serializable接口才能被Java默认机制序列化。 HashMapString已经实现了这个接口,因此可以成功地进行序列化。
请参阅Sun自己的序列化教程 - 它非常简短,我认为应该涵盖您在简单情况下所需的所有内容。 (您只需要将Map对象序列化到流中,然后在后续运行中读取它)。
如果遇到问题,请尝试使用一些虚拟值对简单的HashMap<String,String>进行序列化。 如果成功了,那么问题就出在你自己的类可序列化性上(以某种方式); 或者,如果这没有起作用,您可以先专注于基本结构,然后再将自己的类添加进来。
如果您有任何更具体的问题无法自行解决,请回复此帖。

0

序列化哈希映射: 这段代码运行良好,我已经在我的应用程序中实现并使用了它。请根据您的需求编写相应的函数以保存和检索映射。

重要的是,您需要确认作为映射值放置的对象必须是可序列化的,也就是说,它们应该实现Serializable接口。例如, Map<.String,String> hashmap=new HashMap<.String,String>().. 在这一行中...map和string都是隐式可序列化的,因此我们不需要为这些显式地实现serializable,但如果您放置自己的对象,则必须是可序列化的。


public static void main(String arr[])
{
  Map<String,String> hashmap=new HashMap<String,String>();
 hashmap.put("key1","value1");
    hashmap.put("key2","value2");
    hashmap.put("key3","value3");
    hashmap.put("key4","value4");

     FileOutputStream fos;
    try {
        fos = new FileOutputStream("c://list.ser");

    ObjectOutputStream oos = new ObjectOutputStream(fos);
     oos.writeObject(hashmap);
     oos.close();

     FileInputStream fis = new FileInputStream("c://list.ser");
     ObjectInputStream ois = new ObjectInputStream(fis);
    Map<String,String> anotherList = (Map<String,String>) ois.readObject();

     ois.close();

     System.out.println(anotherList);

 } catch (FileNotFoundException e) {e.printStackTrace();
 } catch (IOException e) {e.printStackTrace();
    } catch (ClassNotFoundException e) {e.printStackTrace();
    }

}

0

是的,如果你想将一个对象写入文件系统,那么这个对象必须实现 Serializeable 接口。这里有一个教程可以帮助你。


你不需要实现Serializable接口,除非你想将Java序列化格式作为你的文件格式。 - Raedwald
2
这不是提问者想要的吗?他正在使用对象输入/输出流进行操作... - David Weiser
谢谢教程,正在阅读! - jazz99

0

在你更了解Serializable的用途之前,不必费心让它可序列化。你需要查看FileWriter并搜索“java文件io”。将数据写入CSV是一个不错的方法。

例如:

key1,key2,key3 valuea1,valuea2,valuea3 valueb1,valueb2,valueb3

希望这可以帮到你。


为什么 CSV 比序列化更好?序列化不需要额外的代码,而你需要自己编写 CSV 格式化/解析代码。 - jtahlborn
我们倾向于避免使用可序列化对象,除非我们绝对必须使用它们。人们意识到的不止这些。像Raedwald一样,我受到Bloch的“Effective Java”的影响。 - Speck
2
CSV 有其自身的缺陷。如何转义分隔符?如何转义转义字符?等等...我仍然不认为它是这么简单的东西的更好替代品。 - jtahlborn
对于这么简单的事情,任何一种选择都可能是可以接受的。处理分隔符并不复杂。我只是想说人们需要意识到序列化的成本。 - Speck
我们对他的应用程序一无所知。虽然建议其他序列化方式是个好主意(CSV也是序列化,只不过不是二进制),但这不应该成为答案,而应该在评论中提出。此外,这应该是对他的应用程序的好奇问题的跟进。 - Mads Buch

0
我建议不要使用Serializable;它比起一开始看起来要难得多。似乎只需添加implements Serializable就足够了。但实际上,这会对您的代码添加许多限制,在实际软件开发中很难处理(而不是在学校)。要了解这些限制有多可怕,请参阅Bloch的书籍Effective Java (second edition)

1
我同意Serializable对于极其持久的数据来说并不是很有效,但是对于临时持久性而无需查询或数据管理的情况,我认为它表现良好。 - Jé Queue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接