【问题标题】:How to read and write a HashMap to a file?如何读取和写入 HashMap 到文件?
【发布时间】:2010-07-27 20:07:21
【问题描述】:

我有以下 HashMap

HashMap<String,Object> fileObj = new HashMap<String,Object>();

ArrayList<String> cols = new ArrayList<String>();  
cols.add("a");  
cols.add("b");  
cols.add("c");  
fileObj.put("mylist",cols);  

我将其写入文件如下:

File file = new File("temp");  
FileOutputStream f = new FileOutputStream(file);  
ObjectOutputStream s = new ObjectOutputStream(f);          
s.writeObject(fileObj);
s.flush();

现在我想把这个文件读回一个HashMap,其中Object是一个ArrayList。 如果我只是这样做:

File file = new File("temp");  
FileInputStream f = new FileInputStream(file);  
ObjectInputStream s = new ObjectInputStream(f);  
fileObj = (HashMap<String,Object>)s.readObject();         
s.close();

这并没有以我保存它的格式给我对象。 它返回一个包含 15 个 null 元素和 对在第 3 个元素的表。我希望它只返回一个具有我一开始提供给它的值的元素。
//如何将同一个对象读回HashMap?

好的,所以根据 Cem 的注释:这似乎是正确的解释:

ObjectOutputStream 以 ObjectInputStream 可以理解反序列化的任何格式序列化对象(在这种情况下为 HashMap),并且通常对任何 Serializable 对象执行此操作。 如果您希望它以您希望的格式序列化,您应该编写自己的序列化器/反序列化器。

在我的例子中:当我从文件中读回 Object 并获取数据并用它做任何我想做的事情时,我只需遍历 HashMap 中的每个元素。 (它只在有数据的地方进入循环)。

谢谢,

【问题讨论】:

  • “没有以我保存的格式给我对象”是什么意思?提供一些您所看到的和您期望的示例。
  • 为什么你的 HashMap 没有声明为HashMap&lt;String,List&lt;String&gt;&gt;
  • +1 用于 HashMap>
  • 它返回一个包含 15 个空元素的表,并且在第三个元素处有 对。我希望它只返回一个具有我一开始提供给它的值的元素。
  • 15 个空元素的键是什么? fileObj.size() 的结果是什么?

标签: java file file-io hashmap


【解决方案1】:

您似乎将 HashMap 的内部表示与 HashMap 的行为方式混淆了。集合是一样的。这里有一个简单的测试来证明给你看。

public static void main(String... args)
                            throws IOException, ClassNotFoundException {
    HashMap<String, Object> fileObj = new HashMap<String, Object>();

    ArrayList<String> cols = new ArrayList<String>();
    cols.add("a");
    cols.add("b");
    cols.add("c");
    fileObj.put("mylist", cols);
    {
        File file = new File("temp");
        FileOutputStream f = new FileOutputStream(file);
        ObjectOutputStream s = new ObjectOutputStream(f);
        s.writeObject(fileObj);
        s.close();
    }
    File file = new File("temp");
    FileInputStream f = new FileInputStream(file);
    ObjectInputStream s = new ObjectInputStream(f);
    HashMap<String, Object> fileObj2 = (HashMap<String, Object>) s.readObject();
    s.close();

    Assert.assertEquals(fileObj.hashCode(), fileObj2.hashCode());
    Assert.assertEquals(fileObj.toString(), fileObj2.toString());
    Assert.assertTrue(fileObj.equals(fileObj2));
}

【讨论】:

    【解决方案2】:

    我相信你犯了一个常见的错误。使用后忘记关闭流!

     File file = new File("temp");  
     FileOutputStream f = new FileOutputStream(file);  
     ObjectOutputStream s = new ObjectOutputStream(f);          
     s.writeObject(fileObj);
     s.close();
    

    【讨论】:

    • 没有。我已经关闭了流。我只是没有在代码中提到它。我现在已经进行了编辑。
    • 无论如何,f.close() 不会正确关闭ObjectOutputStream。您应该始终在最上面的装饰流上调用 close,即 s.close()
    【解决方案3】:

    您还可以使用 JSON 文件来读取和写入 MAP 对象。

    将地图对象写入 JSON 文件

        ObjectMapper mapper = new ObjectMapper();
    
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "Suson");
        map.put("age", 26);
    
        // write JSON to a file
        mapper.writeValue(new File("c:\\myData.json"), map);
    

    从 JSON 文件中读取地图对象

        ObjectMapper mapper = new ObjectMapper();
    
            // read JSON from a file
            Map<String, Object> map = mapper.readValue(
                    new File("c:\\myData.json"),
                    new TypeReference<Map<String, Object>>() {
            });
    
            System.out.println(map.get("name"));
            System.out.println(map.get("age"));
    

    并从 com.fasterxml.jackson 导入 ObjectMapper 并将代码放入 try catch 块中

    【解决方案4】:

    你的第一行:

    HashMap<String,Object> fileObj = new HashMap<String,Object>();
    

    让我暂停一下,因为不能保证这些值是Serializable,因此可能无法正确写出。你真的应该将对象定义为HashMap&lt;String, Serializable&gt;(或者如果你愿意,简单的Map&lt;String, Serializable&gt;)。

    我还会考虑以简单的文本格式(例如 JSON)序列化 Map,因为您正在执行简单的 String -&gt; List&lt;String&gt; 映射。

    【讨论】:

    • 出现这些行的类本身是可序列化的。
    【解决方案5】:

    我相信你得到了你所节省的。您在保存地图之前检查过地图吗?在HashMap:

    /**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 16;
    

    例如默认的 HashMap 将从 16 nulls 开始。您使用其中一个存储桶,因此您在保存时只剩下 15 个nulls,这是您加载时得到的。 尝试检查 fileObj.keySet().entrySet().values() 以了解您的期望。

    HashMaps 的设计目的是在牺牲内存的同时提高速度。有关详细信息,请参阅Wikipedia's Hash table 条目。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-15
      • 1970-01-01
      • 1970-01-01
      • 2021-10-12
      • 2014-12-29
      • 1970-01-01
      • 1970-01-01
      • 2016-08-20
      相关资源
      最近更新 更多