Sérialiser une arraylist [Résolu]

el_teedee 498 Messages postés mercredi 7 juillet 2004Date d'inscription 13 juillet 2015 Dernière intervention - 22 juin 2005 à 17:09 - Dernière réponse : scoubidou944 728 Messages postés mardi 22 avril 2003Date d'inscription 19 janvier 2017 Dernière intervention
- 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)



Voilà ce que j'ai essayé :

private void ArrayListToXML_Click(object sender, System.EventArgs e)

{

XmlSerializer serialiseur = new XmlSerializer(typeof(Fichier));

TextWriter writer = new StreamWriter("monfichier.xml");

Fichier coucou;

foreach (object o in al)

{

coucou = (Fichier)o;

serialiseur.Serialize(writer,coucou);

}

writer.Close();

}



Alors, avec une seule instance dans l'arraylist, ca marche, voici le contenu du fichier XML :



<?xml
version="1.0" encoding="utf-8" ?>





[# -] <Fichier xmlns:xsd=" http://www.w3.org/2001/XMLSchema " xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance">






<numero>2</numero>





<date_debut>2005-06-22T17:02:52.3750000+02:00</date_debut>





<date_fin>2005-06-22T17:02:52.3750000+02:00</date_fin>





<duree>60</duree>





<statut>nouveau</statut>





<materiel>Epandeur 1</materiel>



</Fichier>




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


<Fichier xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-^


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
Afficher la suite 

Votre réponse

26 réponses

Meilleure réponse
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 22 juin 2005 à 17:43
3
Merci
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);


try
{
serializer.Serialize(writer, fc);
}
catch
{
throw;
}
finally
{
writer.Close();
serializer = null;
}
}

[Pub] http://www.csharpfr.com/auteurdetail.aspx?ID=13319 [\Pub]
C# forever

Merci cs_Bidou 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 121 internautes ce mois-ci

Commenter la réponse de cs_Bidou
Meilleure réponse
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 23 juin 2005 à 17:20
3
Merci
Ouaip, bien vu SharpMao..


XmlSerializer xs = new XmlSerializer( typeof( ArrayList ), new Type[ ] { typeof( Fichier ) } );


TextWriter wr = new StreamWriter( "MyFile.xml" );


xs.Serialize( wr, list );


wr.Close();

Merci Lutinore 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 121 internautes ce mois-ci

Commenter la réponse de Lutinore
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 22 juin 2005 à 18:30
0
Merci
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.
Commenter la réponse de Lutinore
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 22 juin 2005 à 18:52
0
Merci
Tu peux essayer ca :

ArrayList list = new ArrayList( );

list.Add( 0 );
list.Add( 1 );

XmlSerializer xs = new XmlSerializer( typeof( ArrayList ) );
TextWriter wr = new StreamWriter( "MyFile.xml" );
xs.Serialize( wr, list );
wr.Close();
Commenter la réponse de Lutinore
SharpMao 1025 Messages postés mardi 4 février 2003Date d'inscription 7 juin 2010 Dernière intervention - 23 juin 2005 à 08:31
0
Merci
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.

Amicalement, SharpMao
Commenter la réponse de SharpMao
el_teedee 498 Messages postés mercredi 7 juillet 2004Date d'inscription 13 juillet 2015 Dernière intervention - 23 juin 2005 à 14:11
0
Merci
Merci pour toutes vos réponses, j'ai pu tester ca ce matin. J'ai au passage apris comment on faisait une collection.



Voilà ce que j'arrive à écrire dans le fichier XML :


<?xml
version= "1.0" encoding="utf-8" ?>





[# -] <ArrayOfFichier xmlns:xsd=" http://www.w3.org/2001/XMLSchema " xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance">






[# -] <Fichier>






<numero>1</numero>





<date_debut>2005-06-23T12:29:41.6875000+02:00</date_debut>





<date_fin>2005-06-23T12:29:41.6875000+02:00</date_fin>





<duree>60</duree>





<statut>nouveau</statut>





<materiel>Epandeur 1</materiel>

</Fichier>








[# -] <Fichier>






<numero>2</numero>





<date_debut>2005-06-23T12:29:46.2187500+02:00</date_debut>





<date_fin>2005-06-23T12:29:46.2187500+02:00</date_fin>





<duree>50</duree>





<statut>téléchargé</statut>





<materiel>Epandeur 1</materiel>



</Fichier>










</ArrayOfFichier>



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.
Commenter la réponse de el_teedee
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 23 juin 2005 à 14:36
0
Merci
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 !??
Commenter la réponse de Lutinore
el_teedee 498 Messages postés mercredi 7 juillet 2004Date d'inscription 13 juillet 2015 Dernière intervention - 23 juin 2005 à 15:11
0
Merci
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 ?
Commenter la réponse de el_teedee
el_teedee 498 Messages postés mercredi 7 juillet 2004Date d'inscription 13 juillet 2015 Dernière intervention - 23 juin 2005 à 16:15
0
Merci
J'ai donc essayé la désérialisation de ma collection, ca marche, c cool !



Par contre, j'ai voulu tester ta méthode Lutinore. Voilà ce que j'ai tapé :

private void ArrayListToXML_Click(object sender, System.EventArgs e)

{

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.
Commenter la réponse de el_teedee
SharpMao 1025 Messages postés mardi 4 février 2003Date d'inscription 7 juin 2010 Dernière intervention - 23 juin 2005 à 16:27
0
Merci
Pour que ça marche avec les ArrayList, le serializer doit connaître tous les types utilisés.

XmlSerializer xs = new XmlSerializer(typeof(ArrayList), new Type[]{mon_fichier.GetType()});

Amicalement, SharpMao
Commenter la réponse de SharpMao
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 23 juin 2005 à 17:31
0
Merci
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..
Commenter la réponse de Lutinore
el_teedee 498 Messages postés mercredi 7 juillet 2004Date d'inscription 13 juillet 2015 Dernière intervention - Modifié par NHenry le 26/05/2018 à 17:35
0
Merci
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>
Commenter la réponse de el_teedee
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 23 juin 2005 à 17:41
0
Merci
Super, on s'améliore tous comme ca.. Mais sur ce coup je crois que c'est SharpMao qui mérite d'etre en VERT : )
Commenter la réponse de Lutinore
SharpMao 1025 Messages postés mardi 4 février 2003Date d'inscription 7 juin 2010 Dernière intervention - 23 juin 2005 à 17:46
0
Merci
Je suis d'accord avec toi el_teedee, la solution de Lutinore est plus élégante.

Je voulais juste montrer comment le faire avec des ArrayList.

Amicalement, SharpMao
Commenter la réponse de SharpMao
scoubidou944 728 Messages postés mardi 22 avril 2003Date d'inscription 19 janvier 2017 Dernière intervention - 23 juin 2005 à 18:10
0
Merci
et maintenant je pose la question piège, si la classe Fichier contient une Hashtable ?

(genre une hash de chak mot à laquelle correspond sa position dans le fichier).


Pour mon cas, j'utilise aussi XmlSerializer mais je n'ai trouvé ma vie sur le net qui s'intègre direct dans mon code.


----------------------------
C++ forever
C# amateur
Commenter la réponse de scoubidou944
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 24 juin 2005 à 08:18
0
Merci
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.

[Pub] http://www.csharpfr.com/auteurdetail.aspx?ID=13319 [\Pub]
C# forever
Commenter la réponse de cs_Bidou
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 24 juin 2005 à 08:24
0
Merci
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.

[Pub] http://www.csharpfr.com/auteurdetail.aspx?ID=13319 [\Pub]
C# forever
Commenter la réponse de cs_Bidou
el_teedee 498 Messages postés mercredi 7 juillet 2004Date d'inscription 13 juillet 2015 Dernière intervention - 24 juin 2005 à 09:10
0
Merci
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)



Voili voilou...
Commenter la réponse de el_teedee
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 24 juin 2005 à 09:26
0
Merci
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();


try
{
formatter.Serialize(new FileStream(fileName, FileMode.Create), h);
}
catch
{
...
}
finally
{
...
}
}

[Pub] http://www.csharpfr.com/auteurdetail.aspx?ID=13319 [\Pub]
C# forever
Commenter la réponse de cs_Bidou
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 24 juin 2005 à 09:36
0
Merci
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.

[Pub] http://www.csharpfr.com/auteurdetail.aspx?ID=13319 [\Pub]
C# forever
Commenter la réponse de cs_Bidou

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.

Sérialiser une arraylist - page 2