Dans le cours : Découvrir Java Standard Edition 8

Écrire directement des objets

Pour illustrer les possibilités offertes par java.io, nous allons donc sauvegarder nos informations ailleurs que dans un fichier texte. Donc actuellement j'ouvre un fichier texte, j'écris à l'intérieur, ça c'est la vidéo précédente. Et bien en fait je peux imaginer de stocker directement un objet. Alors je vais me placer carrément en dehors des blocs try catch comme ça nous verrons la levée d'exception. Donc je vais créer maintenant un objet de type FileOutputStream qui représente un fichier dit binaire. Donc dans la même veine que précédemment je dois créer un objet FileOutputStream, je lui donne le nom de data.ser. Alors la différence entre un File Writer et un FileOutputStream, c'est que FileOutputStream, par défaut, possède une méthode qui lui permet d'écrire, par ici, des octets. Et même la méthode write int en réalité va écrire des octets. Donc normalement ce que l'on fait par ici c'est de fermer le fichier : ça c'est la bonne pratique. A priori comme on le voit là, on me demande de gérer des exceptions FileNotFoundException dans le cas de l'ouverture. Pour le close, c'est un IOException et pour les Write ce seront aussi des IOException. Je vais utiliser un filtre assez élaboré c'est ObjectOutputStream. Un ObjectOutputStream, c'est un objet qui permet ou qui fournit des services pour écrire directement un objet dans un flux. Donc je vais sur l'objet FIS construire mon ObjectOutputStream. De la même façon que j'ai importé FileOutputStream, je dois importer ObjectOutputStream et ici fermer ObjectOutputStream. Une fois que j'ai créé mon ObjectOutputStream, pour écrire un objet directement dans le flux j'utilise WriteObject. Par exemple l'objet qu'il pourrait être intéressant d'écrire, c'est Objet population puisque je conserverai dans un fichier et donc rendrai persistant un objet qui contient tous les mobiles et donc en particulier le meilleur mobile. À partir du moment où j'écris l'objet population tout ce qu'il contient, donc si je vais revoir la classe population je vais trouver la liste des mobiles, va être sérialisé. Autrement dit je vais écrire dans le fichier la population et ses mobiles. Alors par contre les ouvertures de fichiers, les ouvertures, les créations d'objets, les écritures dans le fichier, etc, demandent la gestion des exceptions. Pour travailler proprement avec les exceptions voilà ce que je pourrais faire : utiliser ce qu'on appelle le try with resources donc ça consiste à définir l'ensemble des objets que je veux manipuler, créer un bloc utilisant donc ces objets FileOutputStream, etc. Ce bloc de try with resources, donc faut faire attention à la syntaxe de ce bloc, va garantir que ObjectOutputStream et le fis qui est en dessous, sous-jacent, vont être fermés j'ai pas besoin du close. Ensuite je peux mettre mes catch qui vont bien. Donc ici Catch exception par exemple avec bien sûr L'affichage de l'erreur. Ça c'est donc une syntaxe particulière sur la gestion des erreurs liées aux objets qui gèrent des ressources externes à la mémoire donc typiquement le cas des fichiers. Ça vous garantit que le close est réellement réalisé parce que si on commence à jouer avec les try catch, il y a une chance sur dix que on finisse par fermer la totalité des flux. Donc ici j'écris la totalité de la population. Alors si j'exécute maintenant le code, je vais avoir normalement une surprise, cette surprise est inévitable, c'est qu'au moment d'écrire dans le flux on se rend compte ou le runtime se rend compte que la classe population n'est pas sérialisable NotSerializableException. Il y a un contrôle au moment de la sérialisation et de l'écriture de l'objet population dans le flux, c'est que la classe population soit prévue pour être sérialisée. Alors ça, ça se fait en implémentant une interface de java.io qui s'appelle serializable donc un import de java.io pour serializable pour garantir que ce qui va passer dans le flux est vraiment sérialisable. Alors pourquoi ? Et bien parce que si maintenant j'exécute la sérialisation, pour population c'est bon mais le runtime se rend compte que le mobile intelligent ne l'est pas sérialisable car effectivement la population référence aujourd'hui des mobiles et des mobiles intelligents. Je peux donc venir sur la classe mobile, la classe mère de mobile intelligent pour le rendre à son tour sérialisable. Donc je vais venir faire un import voilà de serializable. Maintenant la sérialisation de la population entraîne la sérialisation du mobile intelligent mais le mobile intelligent pointe lui-même vers la matrice, etc. Le mécanisme de sérialisation est extrêmement puissant, il sérialise la totalité du graphe. Mais il faut que tous les objets qui sont à écrire soit marqués serializable. Donc serializable avec un import et normalement avec la matrice on est arrivé au bout du graphe donc on a stocké dans le fichier la totalité des données. Si maintenant on va regarder à quoi ressemble le projet, on se rend compte qu'effectivement il y a un data.ser qui a été écrit. Si on essaie de l'ouvrir, alors ouvrir avec, il faudrait donc le bloc-notes par exemple, on se rend compte très vite qu'il ne s'agit pas du tout d'un fichier texte et que alors certes on reconnaît des morceaux mais que globalement on est devant une écriture binaire qui n'est pas accessible au bloc-notes. Donc dans cette vidéo nous avons montré l'usage d'un filtre qui permet d'écrire directement des objets dans un flux. Nous avons montré le try with resources, écriture d'un try catch qui est assez classique avec des outils comme les fichiers qui sont des outils qui maintiennent des handlers vers l'extérieur de la mémoire. Et nous avons montré donc la possibilité de rendre persistants des objets. On pourrait imaginer dans un autre morceau de code relire la population qu'on vient d'écrire pour la ré-exécuter, la réutiliser.

Table des matières