Je veux sérialiser des objets en chaînes, et inversement.
Nous utilisons protobuf-net pour transformer un objet en un flux et inversement, avec succès.
Cependant, diffuser en chaîne et retour ... pas si réussi. Après avoir passé StreamToString
et StringToStream
, la nouvelle Stream
n’est pas Désérialisée par protobuf-net; il déclenche une exception Arithmetic Operation resulted in an Overflow
. Si nous désérialisons le flux d'origine, cela fonctionne.
Nos méthodes:
public static string StreamToString(Stream stream)
{
stream.Position = 0;
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
public static Stream StringToStream(string src)
{
byte[] byteArray = Encoding.UTF8.GetBytes(src);
return new MemoryStream(byteArray);
}
Notre exemple de code utilisant ces deux:
MemoryStream stream = new MemoryStream();
Serializer.Serialize<SuperExample>(stream, test);
stream.Position = 0;
string strout = StreamToString(stream);
MemoryStream result = (MemoryStream)StringToStream(strout);
var other = Serializer.Deserialize<SuperExample>(result);
C'est si commun mais si profondément faux. Les données Protobuf ne sont pas des données de chaîne. Ce n'est certainement pas ASCII. Vous utilisez l'encodage à l'envers . Un encodage de texte transfère:
Vous n'avez pas "octets formatés". Vous avez octets arbitraires. Vous devez utiliser quelque chose comme un code base-n (généralement: base-64). Cela transfère
regardez Convert.ToBase64String et Convert. FromBase64String
Je viens de tester cela et fonctionne bien.
string test = "Testing 1-2-3";
// convert string to stream
byte[] byteArray = Encoding.ASCII.GetBytes(test);
MemoryStream stream = new MemoryStream(byteArray);
// convert stream to string
StreamReader reader = new StreamReader(stream);
string text = reader.ReadToEnd();
Si vous avez déjà écrit stream
, vous voudrez peut-être aller au début avant de lire le texte: stream.Seek(0, SeekOrigin.Begin);
Lorsque vous testez, essayez avec UTF8
Encoder le flux comme ci-dessous
var stream = new MemoryStream();
var streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8);
Serializer.Serialize<SuperExample>(streamWriter, test);
Essaye ça.
string output1 = Encoding.ASCII.GetString(byteArray, 0, byteArray.Length)
une conversion de UTF8 MemoryStream en chaîne:
var res = Encoding.UTF8.GetString(stream.GetBuffer(),0 , stream.GetBuffer().Length)
J'ai écrit une méthode utile pour appeler n'importe quelle action prenant une StreamWriter
et l'écrire en chaîne. La méthode est comme ça;
static void SendStreamToString(Action<StreamWriter> action, out string destination)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream, Encoding.Unicode))
{
action(writer);
writer.Flush();
stream.Position = 0;
destination = Encoding.Unicode.GetString(stream.GetBuffer(), 0, (int)stream.Length);
}
}
Et vous pouvez l'utiliser comme ça;
string myString;
SendStreamToString(writer =>
{
var ints = new List<int> {1, 2, 3};
writer.WriteLine("My ints");
foreach (var integer in ints)
{
writer.WriteLine(integer);
}
}, out myString);
Je sais que cela peut être fait beaucoup plus facilement avec un StringBuilder
, le fait est que vous pouvez appeler n'importe quelle méthode prenant un StreamWriter
.
Je veux sérialiser des objets en chaînes, et inversement.
XmlSerializer est différent des autres réponses, mais le moyen le plus simple de faire exactement cela pour la plupart des types d'objet est:
Subject subject = new Subject();
XmlSerializer serializer = new XmlSerializer(typeof(Subject));
using (Stream stream = new MemoryStream())
{
serializer.Serialize(stream, subject);
// do something with stream
Subject subject2 = (Subject)serializer.Deserialize(stream);
// do something with subject2
}
Toutes vos propriétés publiques des types pris en charge seront sérialisées. Même certaines structures de collection sont prises en charge et seront intégrées aux propriétés de sous-objet. Vous pouvez contrôler le fonctionnement de la sérialisation avec attributs sur vos propriétés.
Cela ne fonctionne pas avec tous les types d'objet, certains types de données ne sont pas pris en charge pour la sérialisation, mais globalement, ils sont assez puissants et vous n'avez pas à vous soucier de l'encodage.
Dans le cas où vous voulez sérialiser/désérialiser des POCO, la bibliothèque JSON de Newtonsoft est vraiment bonne. Je l'utilise pour conserver les POCO dans SQL Server sous forme de chaînes JSON dans un champ nvarchar. La mise en garde est que puisque sa dé/sérialisation n'est pas vraie, il ne conservera pas les membres privés/protégés et la hiérarchie de classes.