Se eliminó la eliminación adecuada de objetos por brevedad, pero me sorprende si esta es la forma más sencilla de codificar un objeto como UTF-8 en la memoria. Tiene que haber una manera más fácil, ¿no?
var serializer = new XmlSerializer(typeof(SomeSerializableObject));
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);
serializer.Serialize(streamWriter, entry);
memoryStream.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(memoryStream, System.Text.Encoding.UTF8);
var utf8EncodedXml = streamReader.ReadToEnd();
c#
xml
utf-8
xml-serialization
Garry Shutler
fuente
fuente
utf8EncodedXml
es UTF-16.Respuestas:
Su código no almacena el UTF-8 en la memoria cuando lo vuelve a leer en una cadena, por lo que 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 sea forzado a hacerlo).
Para obtener los octetos UTF-8 reales, puede usar:
Dejé fuera la misma disposición que usted dejó. Estoy un poco a favor de lo siguiente (dejando la eliminación normal):
Lo que es casi la misma cantidad de complejidad, pero muestra que en cada etapa hay una opción razonable para hacer otra cosa, la más urgente de las cuales es serializar en otro lugar que no sea la memoria, como un archivo, TCP / IP. flujo, base de datos, etc. En general, no es tan detallado.
fuente
XmlWriter.Create(memoryStream, new XmlWriterSettings { Encoding = new UTF8Encoding(false) })
.No, puede usar a
StringWriter
para deshacerse del intermedioMemoryStream
. Sin embargo, para forzarlo a XML, debe usar unStringWriter
que anule laEncoding
propiedad:O si aún no está usando C # 6:
Luego:
Obviamente, puede convertirlo
Utf8StringWriter
en una clase más general que acepte 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 unStringWriter
:)Ahora, como dice Jon Hanna, esto seguirá siendo UTF-16 internamente, pero presumiblemente lo pasará a otra cosa en algún momento, para convertirlo en datos binarios ... en ese momento puede usar la cadena anterior, conviértalo en bytes UTF-8 y todo estará bien, porque la declaración XML especificará "utf-8" como codificación.
EDITAR: Un ejemplo breve pero completo para mostrar este funcionamiento:
Resultado:
Tenga en cuenta la codificación declarada de "utf-8" que es lo que queríamos, creo.
fuente
TextWriter.Encoding
serializador XML utiliza la propiedad para determinar qué nombre de codificación especificar dentro del documento.XmlWriter
hágalo con el método de fábrica que toma unXmlWriterSettings
objeto y tiene laOmitXmlDeclaration
propiedad establecida entrue
.Utf8StringWriter
solución es extremadamente agradable y limpiaMuy buena respuesta usando herencia, solo recuerde anular el inicializador
fuente
Encontré esta publicación de blog que explica muy bien el problema y define algunas soluciones diferentes:
(enlace muerto eliminado)
Me he conformado con la idea de que la mejor manera de hacerlo es omitir completamente la declaración XML cuando está en la memoria. Realmente es UTF-16 en ese punto de todos modos, pero la declaración XML no parece significativa hasta que se ha escrito en un archivo con una codificación particular; e incluso entonces no se requiere la declaración. No parece romper la deserialización, al menos.
Como menciona @Jon Hanna, esto se puede hacer con un XmlWriter creado así:
fuente