2017-03-10 55 views
1

我基本上試圖將多個(12,特別是)HashMap字典寫入本地文件,然後檢索它們。到目前爲止,我設法做一個,但是當我嘗試做不止一個時,我基本上不能使它工作。所以任何幫助做到這一點表示讚賞。這裏是我到目前爲止的代碼:Java將多個HashMap寫入文件

private HashMap<String, List<String>> loadDict() { 
    int month = Functions.getMonth(); 

    //load back in 
    FileInputStream fis; 
    try { 
     fis = new FileInputStream(statsFile); 
     ObjectInputStream ois = new ObjectInputStream(fis); 
     for (int i = 0; i < 13; i++) { 
      //itemsDict = (HashMap) ois.readObject(); 
      Object whatisThis = (Object) ois.readObject(); 
      dictionaries.add(whatisThis); 
     } 
     ois.close(); 
     fis.close(); 
    } catch (FileNotFoundException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } catch (IOException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } catch (ClassNotFoundException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } 

    itemsDict = (HashMap) dictionaries.get(month); 
    System.out.println(itemsDict.get("cake")); 
    return itemsDict; 
} 

private void setupDictionaries() { 
    HashMap<String, List<String>> dictionary = new HashMap<String,List<String>>(); 
    FileOutputStream fos; 
    try { 
     fos = new FileOutputStream(statsFile); 
     ObjectOutputStream oos = new ObjectOutputStream(fos); 
     for (int i = 0; i < 13; i++) { 
      oos.writeObject(dictionary); 
     } 
     oos.close(); 
     fos.close(); 
    } catch (FileNotFoundException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 
private void storeThis(String product, String price, String quantity, String date, List<List<String>> myContent) {//after set, replace dictionary in dictionaries array 
    dictionaries.set(Functions.getMonth(), itemsDict); 

    //save the dictionary to the overall statistics file 
    FileOutputStream fos; 
    try { 
     fos = new FileOutputStream(statsFile); 
     ObjectOutputStream oos = new ObjectOutputStream(fos); 
     for (int i = 0; i < 13; i++) { 
      oos.writeObject(dictionaries.get(i)); 
     } 
     //oos.writeObject(itemsDict); 
     oos.close(); 
     fos.close(); 
    } catch (FileNotFoundException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

澄清一下:)setupDictionaries只調用在第一次運行(設置文件),否則loadDict(被稱爲上運行時,所有的字典加載到一個ArrayList 。從數組列表中,應該選擇正確的對象(hashmap),然後將其作爲散列表映射到itemsDict。 storeThis()在按下按鈕時被調用,但是我將代碼減少到只有相關的位。


所以我想實現你曾經建議JSON,到目前爲止我有:

private void setupDictionaries() { 
    ObjectMapper mapper = new ObjectMapper(); 
    ArrayNode arrayNode = mapper.createArrayNode(); 
    JsonNode rootNode = mapper.createObjectNode(); 
    ArrayList<String> myThing = new ArrayList<String>(); 
    myThing.add("hi"); 
    myThing.add("."); 

    itemsDict.put("cake", myThing); 

    JsonNode childNode1 = mapper.valueToTree(itemsDict); 
    ((ObjectNode) rootNode).set("Jan", childNode1); 
    JsonNode childNode2 = mapper.createObjectNode(); 
    ((ObjectNode) rootNode).set("obj2", childNode2); 
    JsonNode childNode3 = mapper.createObjectNode(); 
    ((ObjectNode) rootNode).set("obj3", childNode3); 
    String jsonString; 
    try { 
     jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode); 
     System.out.println(jsonString); 
     ObjectWriter writer = mapper.writer(new DefaultPrettyPrinter()); 
     writer.writeValue(new File(statsFile), jsonString); 
    } catch (JsonProcessingException e2) { 
     // TODO Auto-generated catch block 
     e2.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

問題,我怎麼就能夠加載該回來嗎? (僅一月下方一切例如,一個HashMap)

private HashMap<String, List<String>> loadDict() { 
    ObjectMapper mapper = new ObjectMapper(); 
    try { 
     HashMap<String, ArrayList<String>> map = mapper.readValue(new File(statsFile), new TypeReference<HashMap<String, ArrayList<String>>>() {}); 
     System.out.println(map.get("Jan")); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

有了這個代碼,我將能夠加載它,但是我得到這個異常(因爲我有JSON的內的多個包含HashMap):

JsonMappingException:無法構建的java.util.HashMap的實例:沒有字符串參數的構造函數/工廠方法從字符串值反序列化

(我不知道如何把這裏的例外)

我的JSON:

「{\ r \ n \」Jan \「:{\ r \ n \」cake \「:[\」hi \「,\」。\「] \ r \ n} n「obj2」:{},\ r \ n \「obj3 \」:{} \ r \ n}「

那麼我怎樣才能夠只加載一個特定的月份到散列表?

+3

你能詳細說明爲什麼你「不能使它工作」?究竟發生了什麼問題? – Siguza

+0

爲什麼不只是導入/導出到JSON? – ControlAltDel

+0

也許你正在寫13個HashMap字典而不是12個? – hmatar

回答

1

我肯定會使用Json格式,認爲這種格式(純文本)可以讓您自由地使用編輯器編輯文件。

我會建議使用Jackson庫。

您只需創建一個ObjectMapper並使用它來序列化和反序列化json。讀取documentation我看到你也可以讀寫json文件。

ObjectMapper objectMapper = new ObjectMapper(); 

例如,這條線會將Json字符串轉換爲Map;

Map<String, Object> map = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {}); 

而且你可以在地圖轉換成JSON更容易:

objectMapper.writeValueAsString(json) 

你的問題的其餘部分仍然讀取和寫入文件。

+0

感謝您的建議。您能否給我舉一個例子,說明如何才能實現我打算使用傑克遜的目標?到目前爲止,我一直在挖掘文檔。 – peterxz

+0

@peterxz閱讀地圖'File file = new File(「data/file.json」); Map map = objectMapper.readValue(file,new TypeReference >(){});' – freedev

+0

@peterxz編寫您的地圖:'objectMapper.writeValue( new FileOutputStream(「data/file.json「),map);' – freedev

0

當你有多個獨立增長的列表或等價物,並試圖處理單個文件中的存儲時,問題是你想如何處理重疊。

同樣重要的是您的寫入頻率與讀取數據的頻率有多相關。如果它的主要讀取和長時間暫停都很好,那麼請使用json格式(每次編輯完成後必須重新寫入整個json,讀取操作必須等待操作完成)。

但是,如果讀寫操作大致相等,那麼我認爲您需要考慮將數據拆分爲順序部分 - 類似於數據庫可能執行的操作。

============================================== =================================

例如:

meta-data + 1*1024 bytes of 01st map 
meta-data + 1*1024 bytes of 02nd map 
meta-data + 1*1024 bytes of 03rd map 
.. 
meta-data + 1*1024 bytes of 12th map 
meta-data + 2*1024 bytes of 01st map 
meta-data + 2*1024 bytes of 02nd map 
.. 
meta-data + 2*1024 bytes of 12th map 
meta-data + 3*1024 bytes of 01st map 
... 
and so on.. 

的間位數據會告訴你是否繼續下一部分的任何給定的地圖數據。

============================================== =================================

你還必須考慮一些事情,比如你是否在用硬 - 磁盤(順序訪問)或SSD(隨機訪問),然後決定您要使用哪種方法。

+0

使用這種性能明智的方法應該沒有問題,我只是不知道該怎麼做。我不能說我爲什麼要這樣做,但是我必須以這種方式存儲數據是有原因的。 – peterxz

+0

由於您似乎在使用java,因此您可以擁有一個具有映射數組的bean類,並執行json-serialize和json-反序列化。否則,而不是一個bean,你也可以簡單地擁有一張12張地圖的列表,然後執行轉換。 –

+0

我確實有12張地圖,但是我無法從文件中加載回來。我可以很好地寫入json文件,但是當我嘗試從json文件轉換爲hashmap對象時,我得到一個異常,因爲它試圖將整個文件轉換爲一個地圖對象,但我只想將一個節(因爲這個文件看起來像這樣:Jan:,Feb:等等,我只想爲給定的montH加載hashmap) – peterxz