2009-06-19 4 views
2

J'ai un problème de sérialisation. Je veux convertir un objet en chaîne et vice versa. J'ai deux méthodes utilitaires:Problème de sérialisation

public 
static byte[] Serialize(Object o) 
{ 
    MemoryStream ms = new MemoryStream(); 
    BinaryFormatter bf1 = new BinaryFormatter(); 
    bf1.Serialize(ms, o); 
    byte[] buffer = ms.ToArray(); 
    //string retStr = Convert.ToBase64String(buffer); 
    return buffer; 
} 

public static object Deserialize(byte[] TheByteArray) 
{ 
    //byte[] TheByteArray = Convert.FromBase64String(ParamStr); 
    MemoryStream ms = new MemoryStream(TheByteArray); 
    BinaryFormatter bf1 = new BinaryFormatter(); 
    ms.Position = 0; 
    return bf1.Deserialize(ms); 
} 

Mon code de test est:

Student obj = new Student(); 
obj.UserName = "Admin"; 
obj.Password = "Password"; 
obj.lessonIds = new int[] { 1, 2, 3, 4, 5 }; 
obj.lessonNames= new string[] { "Spanish", "Maths" }; 
obj.Id= 43; 
byte[] retByteArray = Crypto.Serialize(obj); 

Student objNew = new Student(); 
objNew = (Student)Crypto.Deserialize(retByteArray); 

ce code ne fonctionne pas. Le message d'erreur est: Une exception a été émise par la cible d'un appel. Fin du flux rencontré avant que l'analyse ne soit terminée.

Fin mon principal objectif est de convertir l'objet en chaîne, mais je ne peux pas convertir même dans tableau d'octets

+0

Qu'est-ce Cryto référence aussi? –

+0

Ce n'est pas le bogue, mais vous n'avez pas besoin de Étudiant objNew = new Student(); avant d'appeler Désérialiser. Vous ne faites que créer un objet et le remplacer par un autre. –

+0

Re votre commentaire - puis simplement, vous le désérialisez incorrectement. Il * vraiment * ne vaut pas la peine d'essayer d'écrire votre propre code de sérialisation - je recommande fortement d'essayer protobuf-net (mise en garde: je suis l'auteur, mais c'est gratuit). Il a fallu quelques secondes pour appliquer à votre exemple, donnant des résultats très efficaces sans le risque de ces bogues de flux ennuyeux. –

Répondre

0

Vous pourriez souffrir d'une condition de course, parce que vous ne fermez pas le flux de mémoire ou votre formatter lorsque vous » re fait sérialisation.

Essayez ceci:

public 
static byte[] Serialize(Object o) 
{ 
    using (MemoryStream ms = new MemoryStream()) 
    { 
     BinaryFormatter bf1 = new BinaryFormatter(); 
     bf1.Serialize(ms, o); 
     byte[] buffer = ms.ToArray(); 
     //string retStr = Convert.ToBase64String(buffer); 
    } 
    return buffer; 
} 

public static object Deserialize(byte[] TheByteArray) 
{ 
    //byte[] TheByteArray = Convert.FromBase64String(ParamStr); 
    using (MemoryStream ms = new MemoryStream(TheByteArray)) 
    { 
     BinaryFormatter bf1 = new BinaryFormatter(); 
     ms.Position = 0; 
     var result = bf1.Deserialize(ms); 
    } 
    return result; 
} 
+1

Cela ne devrait faire aucune différence dans ce cas ... –

+0

@Marc Vous ne pensez pas? Pourquoi? – Joseph

+2

Vous ne faites rien d'extra dans le code avant d'obtenir le ToArray(), donc vous ne changez pas les résultats. Tout ce que vous ajoutez est un 'Dispose()' à quelque chose qui a une implémentation 'Dispose()' vide. Ne vous méprenez pas, je dispose toujours de ces choses aussi - mais ce n'est pas le bogue. –

1

J'ai juste essayé le code d'origine et l'amende infligée mais le travail, vous devez vous assurer que la définition de la classe des élèves est marqué comme [Serializable]

[Serializable] 
public class Student 
{ 
    public string UserName; 
    public string Password; 
    public int[] lessonIds; 
    public string[] lessonNames; 
    public int Id; 
    public Student() { } 
} 
0

Ce code fonctionne parfaitement pour moi (j'ai simplement ajouté la classe Student manquante.Ce code est-il réellement représentatif de votre code réel. En particulier, la gestion de tampon (peut-être fichier IO) serait ma première suspicion. Mais le bug n'est pas dans le code que vous avez posté ... ça fonctionne bien. En aparté ... BinaryFormatter peut être cassant, en particulier autour de différentes versions - vous pouvez envisager d'autres sérialiseurs. Demander plus d'informations si vous êtes intéressé.

Ici, il est runnable:

using System.IO; 
using System.Runtime.Serialization.Formatters.Binary; 
using System; 
static class Crypto 
{ 
    static byte[] Serialize(object o) 
    { 
     MemoryStream ms = new MemoryStream(); 
     BinaryFormatter bf1 = new BinaryFormatter(); 
     bf1.Serialize(ms, o); 
     byte[] buffer = ms.ToArray(); 
     //string retStr = Convert.ToBase64String(buffer); 
     return buffer; 
    } 

    public static object Deserialize(byte[] TheByteArray) 
    { 
     //byte[] TheByteArray = Convert.FromBase64String(ParamStr); 
     MemoryStream ms = new MemoryStream(TheByteArray); 
     BinaryFormatter bf1 = new BinaryFormatter(); 
     ms.Position = 0; 
     return bf1.Deserialize(ms); 
    } 
    [Serializable] 
    class Student 
    { 
     public string UserName { get; set; } 
     public string Password { get; set; } 
     public int[] LessonIds { get; set; } 
     public string[] LessonNames { get; set; } 
     public int Id { get; set; } 
    } 
    static void Main() 
    { 
     Student obj = new Student(); 
     obj.UserName = "Admin"; 
     obj.Password = "Password"; 
     obj.LessonIds = new int[] { 1, 2, 3, 4, 5 }; 
     obj.LessonNames = new string[] { "Spanish", "Maths" }; 
     obj.Id = 43; 
     byte[] retByteArray = Crypto.Serialize(obj); 

     Student objNew = (Student)Crypto.Deserialize(retByteArray); 
    } 
} 
+0

Pour info, je l'ai couru à travers protobuf-net pour comparaison: BinaryFormatter = 363 octets; protobuf-net = 45 octets ... –

+0

Merci à tous. J'ai trouvé mon erreur. Ma classe d'étudiants implémente l'interface ISerializable; quand je l'enlève, ça marche. Mais je n'ai pas compris le problème avec l'interface. – user125687

Questions connexes