el_teedee
Messages postés497Date d'inscriptionmercredi 7 juillet 2004StatutMembreDernière intervention13 juillet 2015
-
22 juin 2005 à 17:09
scoubidou944
Messages postés714Date d'inscriptionmardi 22 avril 2003StatutMembreDernière intervention19 janvier 2017
-
8 févr. 2006 à 16:23
Bonjour,
alors, je viens de découvrir la sérialisation et juste après, j'ai découvert arraylist dont je ne méttais jamais servi.
Ce que je souhaite, c'est exporter en XML toutes les instances de ma
classe. Alors j'ai pensé mettre toutes ces instances dans un arraylist,
pour ensuite faire la sérialisation de toutes ces instances.
J'ai trouvé la méthode pour sérialiser un objet. Mais apparement, cela pose plus de problème pour un arraylist.
Le but de tout ça : je veux faire du stockage en dehors de mon appli,
je me suis orienté vers XML car je pense que cela correspond à mes
besoins, plus qu'une base de données.
Disons que j'ai une classe Fichier, dont chaque occurence possède 3 ou
4 propriétés d'un fichier. (numéro, statut, et nom du matériel)
Alors en fait, je télécharge d'un boîtier électronique une liste de fichiers avec leurs caractéristiques ci dessus. Je veux stocker cette liste à l'extérieur de l'application pour la retrouver au prochain lancement de cette dernière.
J'aurais donc par exemple dans l'ordre (n°, statut, nom):
instance1 : 1,statut1,machine1
instance2 : 2,statut2,machine2
instance3 : 3,statut2,machine1
Donc 3 instances de ma classe "fichier", que je voudrais pouvoir
retrouver lors de la prochaine exécution de l'appli. (et si possible,
les remettre dans des instances de fichier lors de la désérialisation)
J'arrive donc à la question : Quels est le format à adopter pour le
fichier XML (les balises, l'ordre, etc...car je ne sais pas du tout) et
comment envoyer dans un fichier XML toutes les instances de ma classe
fichier ? Est-ce que je peux passer par un arraylist ? Ou bien il faut
faire la sérialisation instance par instance ? (j'ai essayé cette
dernière solution, mais j'ai eu une erreur qui vient du format des
balises je pense)
Mais, lorsque je crée une deuxième instance, voilà ce que j'obtient dans le contenu du fichier XML :
La page XML ne peut pas être affichée
Impossible d'afficher l'entrée XML en
utilisant la feuille de style XSL. Corrigez l'erreur, puis cliquez sur le bouton
[javascript:location.reload() Actualiser] ou réessayez
ultérieurement.
<hr>
Un seul élément de niveau supérieur est
autorisé dans un document XML. Erreur de traitement de la ressource
file:///D:/SATt...
Si vous en avoir une réponse, moi y'en a écouter vous avec plaisir.
Au passage, je pense que TheSaib a de l'info la dessus, j'ai vu un post à lui qui disait que arraylist n'est pas serialisable. Si tu peux me renseigner un peu plus
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 22 juin 2005 à 17:43
Hello,
Puisque tu as une collection typée (composée uniquement de Fichier) alors tu peux créer une collection (dérivé de CollectionBase, ou utilisé les Generics si tu es sous VS2005). Supposons que cette collection s'appelle fc et est de type FichierCol, alors tu peux écrire pour sauver tout tes objects :
public void SaveFichier(string fileName, FichierCol fc)
{
XmlSerializer serializer = new XmlSerializer(typeof(FichierCol));
TextWriter writer = new StreamWriter(fileName);
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 22 juin 2005 à 18:30
Salut,
ArrayList a l'attribut [ Serializable ] donc ca devrait marcher, tu as essayé ? Je suis pas un spécialiste du XML mais ca me semble normal d'avoir l'erreur "Un seul élément de niveau supérieur est autorisé dans un document XML" si tu serializes instance par instance dans le même fichier.
SharpMao
Messages postés1024Date d'inscriptionmardi 4 février 2003StatutMembreDernière intervention 7 juin 201069 23 juin 2005 à 08:31
La raison pour laquelle ça ne marchait pas :
Comme te la dit le message d'erreur, XML n'accepte qu'une seule racine (Fichier dans ton exemple).
Si tu mets plusieurs <Fichier>, le XML n'est plus valide. Il faut donc une racine commune à ces <Fichier>.
Avec la solution de Lutinor, il va créer une racine , qui contiendra tes Fichiers.
Je n'ai plus qu'à essayer de désérialiser tout cela, pour recréer les deux instances, et retrouver leur contenu.
>Lutinore : sur le lien suivant, TheSaib explique que arraylist n'est pas sérialisable, donc je n'ai pas essayé.
> Bidou : j'ai repris ton exemple avec
ma classe Fichier, j'ai crée une classe Fichiers qui dérive de
CollectionBase. Est-ce que tu peux m'expliquer à quoi try, catch, throw; finally servent ?
Je fais la désérialisation tantôt et je vous tiens au courant. Merci encore.
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 23 juin 2005 à 14:36
Salut, j'avais regardé le lien suite à ton premier message.. Je ne sais pas pourquoi il dit ca.. faut peut etre s'entendre sur sérialiser un ArrayList et sérialiser son contenu !? J'ai pas testé la désérialisation mais le code de sérialisation que je t'ai donné il marche.. Mais la methode de Bidou est très bien de toute facon..
Euh, Bidou j'ai pas compris pourquoi tu relances l'exception dans ton catch !??
el_teedee
Messages postés497Date d'inscriptionmercredi 7 juillet 2004StatutMembreDernière intervention13 juillet 20159 23 juin 2005 à 15:11
Je veux bien entendu exporter le contenu de tous mes objets, pour
pouvoir les retrouver lors d'un second lancement de l'application. Si
j'avais 13 instances, je veux recréer mes 13 instances, avec leurs
propriétés. Je pense que sérialiser / désérialiser permet de faire ça ?
XmlSerializer xs = new XmlSerializer(typeof(ArrayList));
TextWriter wr = new StreamWriter("MyFile.xml");
xs.Serialize(wr,al);
wr.Close();
}
al est mon objet arraylist déclaté dans ma form1 comme suit :
public ArrayList al = new ArrayList(10);
VS .NET 2003 plante à la ligne en vert (donc ca plante à xs.Serialize(wr,al);)et marque :
Une exception non gérée du type 'System.InvalidOperationException' s'est produite dans system.xml.dll
Informations supplémentaires : Erreur lors de la génération du document XML.
J'ai essayé avec :
al.add(0);
al.add(1);
Là ca marche, mais moi, j'ai essayé avec une arraylist al déjà remplie ailleurs mais par un fichier, pas par une valeur (al.add(mon_fichier));
Là ca plante.
Enfin, je n'ai pas pu rajouter [serializable] devant la déclaration de
mon arraylist al car c'est destiné aux classes, struc, et enum et pas
aux variables.
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 23 juin 2005 à 17:31
Ah non tu ne peux pas rajouter [ Serialisable ] à un objet.. Mais Arraylist a deja cet attribut c'est pour ca que dès le debut je t'ai dit que ca devrait marcher.. Mon exemple effectivement fonctionne mais comme il est simplifié, il correspondait pas à ton cas precis.. merci à SharpMao, j'avais pas encore compris l'utilité de ce constructeur..
el_teedee
Messages postés497Date d'inscriptionmercredi 7 juillet 2004StatutMembreDernière intervention13 juillet 20159 Modifié le 26 mai 2018 à 17:35
Yes, d'ailleurs au passage, je préfère la version de Lutinore mon cher SharpMao. (je suis taquin)
En effet, mettre mon_fichier.gettype() suppose que tu
connaisses déjà le nom d'une occurence de la classe Fichier. Ce qui est
mon cas, mais par chance, car j'ai déclaré une variable de type Fichier
nommée Fichier_En_Cours dans ma class form1, pour une autre utilisation.
Le typeof(Fichier) me parait mieux car pas besoin de préciser une instance.
Merci pour tout les gars, ca marche nikel. (les deux méthodes : collection et arraylist)
Si qqln veut mon code, hésitez pas : <Supprimé sur demande>
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 24 juin 2005 à 08:18
Lutinore>
En fait, cette méthode est dans une classe de fonctionnalité (j'ai fait un c/c d'une partie de l'un de mes codes), class qu'on appelle sauf erreur aussi class Métier(?), et dans une telle classe je ne veux pas faire d'affichage graphique (pour annoncer une errreur). Le throw me permet de balancer l'exception plus loin quelque soit son type. Du coup, je la catch dans la partie graphique qui appelle cette méthode (ma winform qui possède un bouton sauver) et je fais un messageMox.
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 24 juin 2005 à 08:24
el_teedee>
Le bloc try-catch-finally me permet de gérer les erreurs. Quand on travaille avec les I/O, on a pleins de problèmes potentiels qui peuvent survenir. Si une erreur se produit lors de la sérialization de mon fichier, le bloc catch va s'exécuter (tu peux traiter ton erreur là). Dans mon cas, je fais un throw, je l'explique pourquoi juste en dessus à Lutinore.
Le bloc finally est un bloc toujours exécuté, erreur ou non. Praque pour faire du nettoyage de ressources, par exemple. En l'occurence je m'en sers pour fermer mes flux.
Sinon la meilleure solution c'est quand même de passer par des collections typées, c'est plus propre et ça facilite énormément la vie. Donc à mon avis tu peux laisser tomber l'ArrayList pour la Serialization ;-) Encore un petit détail, qui est plus une convention, Fichier est un mauvais nom pour une collection, appelle le plutôt FichierCollection ou à la limite Fichiers, mais pas Fichier.
el_teedee
Messages postés497Date d'inscriptionmercredi 7 juillet 2004StatutMembreDernière intervention13 juillet 20159 24 juin 2005 à 09:10
C'est ce que j'ai fait Bidou, ma classe d'éléments "fichier" est nommée
Fichier, (c'est une classe métier, si je ne m'abuse), et ma collection
est une classe nommée Fichiers.
C'est quand même énorme la méthode que tu as montré SharpMao, comme le
dit Lutinore. Si j'ai bien compris, tu lui passes d'une part le
type d'arraylist pour qu'il reconnaissance l'objet conteneur, puis tu
lui passes le type des instances, pour qu'il soit capable de
reconstituer les champs propriétés pour chaque instance. J'espère que
c'est une bonne explication, sinon on m'aurait menti ?
Sinon, j'ai deux autres questions d'ordre général :
1°) ma classe collection est dite typée car elle ne contient que des
objets de type Fichier. Mais à quel endroit on spécifie qu'elle est
typée ? C'est juste selon les constructeurs que l'on y met ? (elle est
typée car elle ne contient qu'un constructeur d'objet Fichier ?)
2°) Qu'elle est succintement la différence entre textwriter,
streamwriter et stringwriter ? J'ai vu qu'il existait les 3, et vu
aussi au passage dans les surchages des méthodes serialize et
deseriallize qu'elle pouvait prendre ces différentes variables:
un System.XML.XMLReader
un System.IO.TextReader
ou un System.IO.Stream (et aussi le system.IO.stringWriter)
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 24 juin 2005 à 09:26
scoubidou>
Je n'ai pas encore compris vraiment pourquoi, mais apparement une Hashtable ne peux pas être sérializée avec un XmlSerializer, cela vient du fait que le constructeur demande un Type, mais ne supporte pas le type Hashtable. Si tu fais un typeof(Hashtable) il retourne une exception disant que la Hashtable implémente IList (?).
La façon de contourner ce problème, c'est de passer par SOAP ou un BinaryFormatter. Je propose un petit exemple vite fait avec SOAP :
Ajouter une référence sur System.Runtime.Serialization.Formatters.Soap
faire un using System.Runtime.Serialization.Formatters.Soap;
Puis
public void SaveFichier(string fileName, Hashtable h)
{
SoapFormatter formatter = new SoapFormatter();
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 24 juin 2005 à 09:36
1)
Avec le framework 2, le nouveau concepte des Generics permet de faire des collections qui sont réellement typées. Comme dans le framework 1.x on n'a pas encore cette notion, on la simule, si on veut bien, avec une CollectionBase qu'on dérive. Cette nouvelle collection contiendra typiquement une méthode Add, pour ton exemple public void Add(Fichier f) pour ajouter un type spécifique d'object => Collection typée. Du point de vue externe (utilisateur de la class), la collection est typée. D'un point de vue interne, on travail avec des objects qu'on cast chaque fois (en Fichier dans ton cas) pour que l'utilisateur est l'impression de travailler avec une collection typée.
2)
Je ne connais pas toutes les définitions des classes par coeur, le mieux c'est de regarder dans la documentation, dans MSDN y'a plus ou moins tout ce qu'il te faut. Mais en gros y'a pleins de possiblités pour lire/ecrire un fichier, et tout dépend la façon qu'on choisit, on a besoin d'un object adapté (textWriter, streamWriter, etc). Du coup, Serialize est surchargée pour pouvoir accepté tout ces types.