web-dev-qa-db-fra.com

Comment lire et écrire un HashMap dans un fichier?

J'ai ce qui suit 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);  

Je l'écris dans un fichier comme suit:

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

Maintenant, je veux lire ce fichier dans un HashMap où l'objet est une liste de tableaux. Si je fais simplement:

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

Cela ne me donne pas l'objet dans le format dans lequel je l'ai enregistré. Il renvoie un tableau avec 15 éléments nuls et la paire <mylist, [a, b, c]> au 3e élément. Je veux qu'il ne renvoie qu'un seul élément avec les valeurs que je lui avais fournies en premier lieu.
// Comment puis-je lire le même objet dans un HashMap?

OK Donc, basé sur la note de Cem: Voici ce qui semble être la bonne explication:

ObjectOutputStream sérialise les objets (HashMap dans ce cas) dans le format que ObjectInputStream comprendra pour désérialiser et le fait de manière générique pour tout objet sérialisable. Si vous voulez qu'il sérialise au format que vous désirez, vous devez écrire votre propre sérialiseur /deserializer.

Dans mon cas: j'itère simplement chacun de ces éléments dans le HashMap lorsque je relis l'objet à partir du fichier et que j'obtiens les données et fais ce que je veux avec. (il n'entre dans la boucle qu'au point où il y a des données.)

Merci,

19
lisam

Vous semblez confondre la représentation interne d'un HashMap avec la façon dont le HashMap se comporte. Les collections sont les mêmes. Voici un test simple pour vous le prouver.

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));
}
13
Peter Lawrey

Je pense que vous faites une erreur courante. Vous avez oublié de fermer le flux après l'avoir utilisé!

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

vous pouvez également utiliser un fichier JSON pour lire et écrire un objet MAP.

Pour écrire un objet de carte dans un fichier 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);

Pour lire un objet de carte à partir d'un fichier 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"));

et importez ObjectMapper depuis com.fasterxml.jackson et mettez le code dans le bloc try catch

2

Votre première ligne:

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

m'a donné une pause, car les valeurs ne sont pas garanties d'être Serializable et peuvent donc ne pas être écrites correctement. Vous devez vraiment définir l'objet comme HashMap<String, Serializable> (ou si vous préférez, simpy Map<String, Serializable>).

J'envisagerais également de sérialiser la carte dans un format de texte simple tel que JSON puisque vous effectuez un simple String -> List<String> mappage.

1
aarestad

Je crois que vous obtenez ce que vous économisez. Avez-vous inspecté la carte avant de l'enregistrer? Dans HashMap:

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

par exemple. la valeur par défaut HashMap commencera par 16 nulls. Vous utilisez l'un des compartiments, de sorte qu'il ne vous reste que 15 nulls lorsque vous enregistrez, ce que vous obtenez lorsque vous chargez. Essayez d'inspecter fileObj.keySet(), .entrySet() ou .values() pour voir ce que vous attendez.

HashMaps sont conçus pour être rapides lors de l'échange de mémoire. Voir Tableau de hachage de Wikipedia entrée pour plus de détails.

1
Stephen