Sé libre de compartir nuestro espacio y códigos con otro, necesitamos tu ayuda para aumentar nuestra comunidad.
Solución:
No, puedes usar un StringWriter
para deshacerse del intermedio MemoryStream
. Sin embargo, para forzarlo en XML necesita usar un StringWriter
que anula el Encoding
propiedad:
public class Utf8StringWriter : StringWriter
public override Encoding Encoding => Encoding.UTF8;
O si aún no está usando C# 6:
public class Utf8StringWriter : StringWriter
public override Encoding Encoding get return Encoding.UTF8;
Entonces:
var serializer = new XmlSerializer(typeof(SomeSerializableObject));
string utf8;
using (StringWriter writer = new Utf8StringWriter())
serializer.Serialize(writer, entry);
utf8 = writer.ToString();
Obviamente puedes hacer Utf8StringWriter
en una clase más general que acepta cualquier codificación en su constructor, pero en mi experiencia, UTF-8 es, con mucho, la codificación “personalizada” más comúnmente requerida para un StringWriter
🙂
Ahora, como dice Jon Hanna, esto seguirá siendo UTF-16 internamente, pero presumiblemente lo pasarás a otra cosa en algún momento, para convertirlo en datos binarios… en ese punto que puede utilizar el anterior stringconviértalo en bytes UTF-8 y todo irá bien, porque la declaración XML especificará “utf-8” como codificación.
EDITAR: un ejemplo breve pero completo para mostrar este funcionamiento:
using System;
using System.Text;
using System.IO;
using System.Xml.Serialization;
public class Test
public int X get; set;
static void Main()
Test t = new Test();
var serializer = new XmlSerializer(typeof(Test));
string utf8;
using (StringWriter writer = new Utf8StringWriter())
serializer.Serialize(writer, t);
utf8 = writer.ToString();
Console.WriteLine(utf8);
public class Utf8StringWriter : StringWriter
public override Encoding Encoding => Encoding.UTF8;
Resultado:
0
Tenga en cuenta la codificación declarada de “utf-8”, que es lo que queríamos, creo.
Su código no obtiene el UTF-8 en la memoria cuando lo vuelve a leer en un string nuevamente, ya no está en UTF-8, sino en UTF-16 (aunque idealmente es mejor considerar las cadenas en un nivel más alto que cualquier codificación, excepto cuando se vea obligado a hacerlo).
Para obtener los octetos UTF-8 reales, podría usar:
var serializer = new XmlSerializer(typeof(SomeSerializableObject));
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);
serializer.Serialize(streamWriter, entry);
byte[] utf8EncodedXml = memoryStream.ToArray();
He dejado fuera la misma disposición que has dejado tú. Estoy ligeramente a favor de lo siguiente (con la eliminación normal dejada):
var serializer = new XmlSerializer(typeof(SomeSerializableObject));
using(var memStm = new MemoryStream())
using(var xw = XmlWriter.Create(memStm))
serializer.Serialize(xw, entry);
var utf8 = memStm.ToArray();
Lo cual tiene la misma cantidad de complejidad, pero muestra que en cada etapa hay una opción razonable para hacer otra cosa, la más apremiante de las cuales es serializar en algún lugar que no sea la memoria, como un archivo, TCP/IP. flujo, base de datos, etc. En general, no es realmente tan detallado.
Muy buena respuesta usando herencia, solo recuerda anular el inicializador
public class Utf8StringWriter : StringWriter
public Utf8StringWriter(StringBuilder sb) : base (sb)
public override Encoding Encoding get return Encoding.UTF8;