IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Problème de Serialisation/Déserialisation binaire d'un objet contenant un arraylist


Sujet :

C#

  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2017
    Messages : 7
    Points : 4
    Points
    4
    Par défaut Problème de Serialisation/Déserialisation binaire d'un objet contenant un arraylist
    Bonjour,

    Je suis actuellement face a un problème de taille (enfin à mon échelle). Alors je dois réaliser une sérialisation/déserialisation en binaire d'un objet qui contient un arraylist dans un programme en C#.
    L'arraylist contient des objets très simple, (un nom + un entier ou boolean)
    Jusque là pas vraiment de soucis, mon code fonctionne (il est basique sans grand intérêt).
    Le programme tourne sous .NET 4.5, Windows 7.
    Mon problème surviens lorsque j'atteint un certains nombre d'objet dans mon arraylist.
    Exemple :
    Mon objet à sérialiser contient un arraylist contenant 50 objets. Aucun soucis j'arrive a sérialiser, déserialiser.
    Mais si j'atteint 70 objets dans mon arraylist alors cela ne fonctionne plus. 70 est la valeur exact c'est a dire que à 69 ça fonctionne et 70 ca ne fonctionne plus.
    Je me retrouve avec un message d'erreur : "Le flux binaire '253' ne contient pas de BinaryHeader valide. Les raisons possibles sont un flux non valide ou une modification de la version de l'objet entre la sérialisation et la désérialisation."


    Je terminerai mon explication par un fait étrange. Mon programme doit fonctionner en .NET 1.1 (Windows XP, Visual Studio 2003) et .NET supérieur à 2.0(Visual Studio 2015), il s'avère que j'ai coder le programme en Visual Studio 2015 (plus ergonomique) puis j'ai porter mon code sous .NET 1.1 (quasiment aucun changement juste une histoire de recréer un projet en Visual Studio 2003 et quelques copié/coller) bref et bien sous .NET 1.1(XP) ca fonctionne parfaitement je peux mettre 3000 objets dans mon arraylist la sérialisation et déserialisation se passe sans soucis.

    Voila je me retourne vers la communauté de Développez.net, si quelqu'un a une idée ou a déjà rencontré le soucis, un peu d'aide serai la bienvenue .

  2. #2
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 757
    Points : 10 697
    Points
    10 697
    Billets dans le blog
    21
    Par défaut
    Bonjour,

    Peut-on avoir le code utilisé pour la sérialisation, ainsi que celui pour la désérialisation ?
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2017
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Bien sur :
    la méthode pour sérialisation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    public static byte[] Serialiser(object classe, System.Type type,  CSerialisation.Type typeDeSerialisation, out string label)
            {
                MemoryStream tamponSerie = new MemoryStream();
     
                TextWriter tw = new StreamWriter(tamponSerie,Encoding.Default,214748364);
                if (typeDeSerialisation == CSerialisation.Type.BIN)
                {
                    BinaryFormatter formatteurBinaire = new BinaryFormatter();
                    formatteurBinaire.Serialize(tamponSerie,classe);
                    label = CSerialisation.Type.BIN.ToString();
                }
                else
                {
                    XmlSerializer formatteurXml = new XmlSerializer(type);
                    formatteurXml.Serialize(tw,classe);
                    label = CSerialisation.Type.XML.ToString();
                }
             return tamponSerie.GetBuffer();
    }


    pour la déserialisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    internal static object DeserialiserSimple(byte[] classeSerialisee, System.Type type, CSerialisation.Type typeDeSerialisation)
            {
                object classeDeserialisee;
                MemoryStream tampon = new MemoryStream(classeSerialisee);
                TextReader tr = new StreamReader(tampon);
                if (typeDeSerialisation == CSerialisation.Type.BIN)
                {
                    BinaryFormatter formatteurBinaire = new BinaryFormatter();
                    classeDeserialisee = formatteurBinaire.Deserialize(tampon);
                }
                else
                {
                    XmlSerializer formatteurXml = new XmlSerializer(type);
                    classeDeserialisee = formatteurXml.Deserialize(tr);                        
                }
                tr.Close();
                return classeDeserialisee;
            }

  4. #4
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 757
    Points : 10 697
    Points
    10 697
    Billets dans le blog
    21
    Par défaut
    Bon, je ne vois rien d'anormal dans les fonctions de sérialisation/désérialisation.

    J'ai fait un petit programme de test avec un ArrayList, et je n'ai pas rencontré de problème non plus.

    Peux-tu nous décrire les objets que tu mets dedans ? Que contiennent-ils ? Quelle taille font-ils ? etc...

    Peux-tu également faire un test : désérialiser immédiatement un ArrayList que tu viens de sérialiser ? Si le problème persiste, cela vient donc très certainement de la sérialisation/désérialisation. Par contre, si le problème ne se présente pas, alors ce n'est pas la désérialisation qui pose un soucis, mais les données à désérialiser qui sont altérées, d'une manière ou d'une autre...
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  5. #5
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2017
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Mes objets dans mon arraylist resemble a ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class Point
        {
            public Point();
            public Point(string paramNom, object paramValeur);
     
            public DateTime datePoint{ get; set; }
            public string Nom { get; set; }
            public string Type { get; set; }
            public object Valeur { get; set; }
        }
    Rien de bien méchant, le champ Valeur ne contient que des booléens ou des entiers (dans de rare cas des strings).
    Effectivement si je réalise ma sérialisation et la ligne d'en dessous la désérialisation, et s'il y a plus de 69 objets dans mon arraylist, ça plante.

    Par contre cela fonctionne parfaitement sur .NET 1.1 (Windows XP), donc j'ai l'impression que de cela vient du .NET(supérieur à 1.1)

  6. #6
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 757
    Points : 10 697
    Points
    10 697
    Billets dans le blog
    21
    Par défaut
    Impossible de reproduire le problème de mon côté.

    Peux-tu réaliser un projet console minimaliste reproduisant le problème, avec juste :
    • la classe Point ;
    • les deux fonctions de sérialisation / désérialisation ;
    • une génération d'un jeu d'essai


    Ensuite, qu'il y ait une différence entre la version 1.1 et les versions ultérieurs ne m'étonne pas plus que cela car :
    • la version 2.0 du framework a apporté de nombreux changement par rapport à la 1.1 (donc possibilité d'implémentation différente) ;
    • le CLR (la machine virtuelle) n'est pas la même.
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  7. #7
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2017
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Pour commencer merci du temps que vous m'accordez.
    Alors j'ai refait un petit projet simple avec mes 3 classes + un main pour tester et le problème persiste.
    Voici mes classes :

    Classe de sérialisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Text;
     
    namespace TestSerialisation
    {
        class maSerialisation
        {
            public string contenu;
            public string type;
            public maSerialisation()
            {
                contenu = null;
                type = null;
            }
            public void Serialiser(object o)
            {
                this.type = o.GetType().ToString();
                MemoryStream tamponSerie = new MemoryStream();
                TextWriter tw = new StreamWriter(tamponSerie, Encoding.Default, 214748364);
                BinaryFormatter formatteurBinaire = new BinaryFormatter();
                formatteurBinaire.Serialize(tamponSerie, o);
                this.contenu = Encoding.Unicode.GetString(tamponSerie.GetBuffer());
            }
            public object Deserialiser()
            {
                object o = null;
                MemoryStream tampon = new MemoryStream(Encoding.Unicode.GetBytes(this.contenu));
                TextReader tr = new StreamReader(tampon);
                BinaryFormatter formatteurBinaire = new BinaryFormatter();
                o = formatteurBinaire.Deserialize(tampon);
                return o;
            }
        }
    }
    Ma classe Point :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    using System;
     
    namespace TestSerialisation
    {
        [Serializable()]
        class Point
        {
     
            public Point()
            {
                Horodate = DateTime.Now;
                Nom = "";
                Type = "";
                Valeur = null;
            }
            public Point(string paramNom, object paramValeur)
            {
                Nom = paramNom;
                Valeur = paramValeur;
                Type = paramValeur.GetType().ToString();
                Horodate = DateTime.Now;
            }
     
            public DateTime Horodate { get; set; }
            public string Nom { get; set; }
            public string Type { get; set; }
            public object Valeur { get; set; }
        }
    }
    Ma classe ObjetList
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    namespace TestSerialisation
    {
        [Serializable()]
        class ObjetList
        {
            public ArrayList malist;
            public ObjetList()
            {
                malist = new ArrayList();
            }
            public void Add(object c)
            {
                malist.Add(c);
            }
        }
    }
    Pour finir ma classe avec le main pour tester le tout :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    using System;
     
    namespace TestSerialisation
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Start");
                ObjetList mList = new ObjetList();
                for (int i = 0; i < 50; i++)
                {
                    Point monPoint = new Point("C.H0.SART", false);
                    mList.Add(monPoint);
                }
                maSerialisation mSer = new maSerialisation();
                mSerJKS.Serialiser(mList);
     
                ObjetList toto = (ObjetList)mSer.Deserialiser();
                int j = 0;
                foreach (object item in toto.malist)
                {
                    j++;
                    Console.WriteLine(j + " : " + item);
                }
                Console.ReadLine();
            }
        }
    }

  8. #8
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 757
    Points : 10 697
    Points
    10 697
    Billets dans le blog
    21
    Par défaut
    Et bien maintenant j'y vois beaucoup plus clair !

    Donc, la première question est : pourquoi les premières fonctions de sérialisation/désérialisation sont différentes de celles fournies dans le dernier exemple ?? Car les premières fonctions sont justes, les secondes erronées.

    Les premières manipulent des byte[], les secondes des string. Et c'est de la que vient le problème, durant les conversions byte[]<->stringToute chaîne de caractères UTF-16 (encodage utilisé en interne en .Net) peut être converti en tableau de byte. Tout tableau de byte ne pas pas être converti en chaîne de caractères UTF-16. Voilà pourquoi la désérialisation ne fonctionne pas correctement tout le temps.

    Donc pour résoudre le soucis, deux possibilités :
    • ou bien utiliser un encodage ASCII 8 bits (attention, Encoding.ASCII est sur 7 bits !!). Par exemple, en utilisant Encoding.GetEncoding(850) pour obtenir le jeu ASCII d'Europe de l'Ouest ;
    • ou bien utiliser des byte[] et non des string.


    Pour l'encodage, qu'importe la page de code employée. La page de code n'est utile que lorsqu'on veut afficher les caractères (ce qui n'est pas le cas ici).
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  9. #9
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2017
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2017
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Effectivement j'avais mal expliquer mon problème étant juste une toute petite partie d'un projet énorme, désolé, et oui je pense que je vais manipuler des tableaux de byte en .NET (supérieur a 2.0) au lieu des string. Je vous remercie j'ai plus qu'a adapté toute ma solution.

    Je note quand même que ce code de pose aucun problème en .NET 1.1 et ne pouvant changer la méthode de sérialisation cela provient d'une veille dll que je n'ai pas le droit de modifier, je vais rester sur l'utilisation des string. en .NET 1.1

    Merci pour votre efficacité et vos conseils avisés ;

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problèmes de serialisation binaire
    Par nicohutse dans le forum VB.NET
    Réponses: 1
    Dernier message: 17/06/2010, 13h44
  2. Web Service : problème de serialisation d'objets
    Par cfeltz dans le forum Silverlight
    Réponses: 2
    Dernier message: 25/05/2009, 15h10
  3. Problème de gestion d'une collection d'objet
    Par poolky dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 17/02/2006, 21h51
  4. Problème avec les données binaire
    Par Lachessis dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 10/08/2005, 17h38
  5. Réponses: 11
    Dernier message: 13/10/2004, 00h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo