Exercice 3  : entrees/sorties 

Sujet de l'exercice

Modifiez les sources de l'exercice précédent pour pouvoir sauvegarder sur disque les commandes et pouvoir les relire. Attention, après une sauvegarde, lorsqu'on relit la commande, on doit se retrouver dans le même etat que lorsqu'on l'avait sauvegardée. Comprendre par là que lors de la lecture, il faut instancier les mêmes objets qui existaient lors de la sauvegarde !

Ce n'est pas aussi simple que cela en a l'air, donc dans un premier temps, vous n'essaierez pas de sauvegarder des commandes comportants des lots d'articles. Essayez juste de sauvegarder une commande comportant des crayons ou des ramettes de papier.

Je vous conseille d'utiliser un  PrintWriter et un BufferedReader pour les lectures/écritures. Pour parser les lignes des fichiers lors de la relecture, utilisez un StringTokenizer
 

Travail a faire

Exemple d'utilisation

Commande c1 = new Commande("Client 1");
Commande c2 = new Commande("Commande lues depuis le disque");

    c1.add(new Stylo(....), 3);
    ....
    c1.write("commande.dat");

    // On initialise c2 a partir de la sauvegarde de c1.
    c2.read("commande.dat");
    ....

Correction

Plusieurs corrections vous sont proposees. La première utilise l'approche "standard" mais oblige a coupler le code des méthodes de sauvegarde/lecture de la commande avec les classes des objets pouvant être sauvegardés. Le code est difficilement maintenable et obige à écrire des modifications dans les fonctions de lecture/ecriture chaque fois que l'on voudra utiliser un nouveau type d'article.

La seconde solution proposée utilise les techniques de "sérialisation des objets". Elle est très esthétique, mais les fichiers sauvegardés ne sont pas humainement lisible, et il faudra faire attention pour pouvoir les relire si vous modifiez le code de votre programme. En effet, un objet sérialisé porte l'"empreinte" de la version de la classe de l'objet au moment de sa sauvegarde. Si vous modifiez le code de la classe de l'objet sérialisé, ou d'une classe d'un membre utilisé par l'objet (et donc sérialisé également), vous ne pourrez plus relire la sauvegarde sans prendre certaines précautions.

La troisieme solution, tres "excitante" au niveau conception objet, utilise les mécanismes d'introspection et de reflexivité du langage Java. Dans cette solution les fonctions d'entrées/sorties ne connaissent pas les classes, les constructeurs et les types des objets qui vont être relus. Tout est dynamique et la fonction de lecture très générique.