2017-03-10 2 views
1

Ich versuche im Grunde, mehrere (12, spezifisch) HashMap Wörterbücher in eine lokale Datei zu schreiben und sie dann abzurufen. Bisher schaffe ich es aber, wenn ich mehr als einen versuche, kann ich es im Grunde nicht schaffen. Also jede Hilfe, um dies zu tun, wird geschätzt. Hier ist mein Code so weit:Java Mehrere HashMaps in Datei schreiben

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(); 
    } 
} 

Ein bisschen Klarstellung: setupDictionaries nur auf dem ersten Lauf (Setup die Datei) aufgerufen wird, ansonsten loadDict() zur Laufzeit aufgerufen wird, alle Wörterbücher in einem Arraylist zu laden . Aus der Arraylist sollte das korrekte Objekt (hashmap) ausgewählt und dann zu itemsDict als hashmap verkettet werden. storeThis() wird aufgerufen, wenn eine Taste gedrückt wird, jedoch reduziere ich den Code auf nur relevante Bits.

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(); 
    } 
} 

Frage, wie würde ich in der Lage sein, diese wieder zu laden: Ich habe


So versuche ich, die JSON Sie bisher vorgeschlagen haben zu implementieren? (Nur alles unter Jan zum Beispiel zu einem 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(); 
    } 
} 

Mit diesem Code würde ich in der Lage sein, es zu laden, jedoch bekomme ich diese Ausnahme (weil ich mehrere Hashmaps im Json habe):

JsonMappingException: Kann nicht Instanz java.util.HashMap konstruieren: keine String-Argument Konstruktor/Factory-Methode von String-Wert deserialisiert

(ich weiß nicht, wie Ausnahmen hier setzen)

Meine JSON:

"{\ r \ n \" Jan \ ": {\ r \ n \ "Kuchen \": [\. "Hallo \" \" \“] \ r \ n}, \ r \ n \ "obj2 \": {}, \ r \ n \ "obj3 \": {} \ r \ n}“

wie würde ich in der Lage sein, nur einen bestimmten Monat in eine hashmap zu laden?

+3

Könnten Sie näher erläutern, warum Sie "es nicht zum Laufen bringen können"? Was läuft genau falsch? – Siguza

+0

Warum importieren/exportieren Sie nicht einfach nur nach JSON? – ControlAltDel

+0

Vielleicht schreiben Sie 13 HashMap-Wörterbücher statt 12? – hmatar

Antwort

1

Ich würde definitiv Json-Format verwenden, bedenken Sie, dass dieses Format (das ist einfacher Text) Ihnen die Freiheit gibt, die Datei mit einem Editor zu bearbeiten.

Ich werde vorschlagen, Jackson Bibliothek zu verwenden.

Sie müssen nur einen ObjectMapper erstellen und verwenden, um den JSON serialisieren und deserialisieren. Lesen Sie die documentation Ich sehe, Sie können auch JSON-Dateien lesen und schreiben.

ObjectMapper objectMapper = new ObjectMapper(); 

Zum Beispiel dieser Linie würde einen JSON-String in ein Map konvertieren;

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

Und Sie können eine Karte in ein Json noch einfacher konvertieren:

objectMapper.writeValueAsString(json) 

Der Rest des Problems bleiben Lesen und Schreiben von Dateien.

+0

Danke für den Vorschlag. Könnten Sie mir bitte ein Beispiel geben, wie ich das erreichen könnte, was ich mit Jackson erreichen möchte? Ich habe in der Dokumentation mit nichts bis jetzt gegraben. – peterxz

+0

@peterxz lesen Sie Ihre Map 'Datei Datei = neue Datei (" data/file.json "); Map map = objectMapper.readValue (Datei, neue TypeReference >() {}); ' – freedev

+0

@peterxz Ihre Karte schreiben:' objectMapper.writeValue ( neue Fileoutputstream ("data/file.json "), map);' – freedev

0

Wenn Sie mehrere unabhängig wachsende Listen oder Ähnliches haben und versuchen, mit der Speicherung in einer einzigen Datei umzugehen, lautet die Frage, wie Sie mit der Überlappung umgehen möchten.

Es ist auch wichtig, wie häufig Sie schreiben und wie oft die Daten gelesen werden. Wenn es meistens liest und lange Pausen in Ordnung sind, dann benutze das json-Format (jedes Mal, wenn eine Änderung gemacht wird, musst du den gesamten json neu schreiben und die Lesevorgänge müssen warten, bis die Operation abgeschlossen ist).

Wenn jedoch lesen und schreiben in etwa gleich wäre, dann denke ich, dass Sie die Daten in sequentielle Abschnitte aufteilen müssen - ähnlich wie es eine Datenbank tun könnte.

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

Zum Beispiel:

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.. 

Die meta- Daten sagen Ihnen, ob Sie mit dem nächsten Abschnitt für die Daten einer bestimmten Karte fortfahren sollen.

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

Sie müssten auch Dinge wie, ob Sie hart verwenden -Diskette (sequentieller Zugriff) oder SSD (random-access) und entscheiden Sie dann, mit welcher Methode Sie gehen möchten.

+0

Es sollte keine Probleme geben, diese Methode leistungsmäßig zu verwenden, ich bin nur nicht sicher, wie es geht. Ich kann nicht sagen, warum ich es auf diese Weise tun will, aber es gibt einen Grund, ich habe auf diese Weise Daten zu speichern. – peterxz

+0

Da Sie scheinen Java zu verwenden, können Sie entweder eine Bean-Klasse, die eine Reihe von Karten und eine json-serialize durchführen und json-deserialisieren das gleiche. Anstelle einer Bean können Sie auch einfach eine Liste von 12 Maps haben und dann die Transformation durchführen. –

+0

Ich habe 12 Karten, aber ich kann die Datei nicht laden.Ich kann sehr gut in die JSON-Datei schreiben, aber wenn ich versuche, von der JSON-Datei in hashmap-Objekt zu konvertieren, bekomme ich eine Ausnahme, weil es versucht, die ganze Datei in ein Map-Objekt zu konvertieren, aber ich möchte nur einen Abschnitt konvertieren (weil die Datei so aussieht: Jan: , Feb: etc, und ich möchte nur die hashmap selbst für einen gegebenen montH laden) – peterxz