O descarte adequado de objetos foi removido por questão de brevidade, mas estou chocado se esta é a maneira mais simples de codificar um objeto como UTF-8 na memória. Tem que haver uma maneira mais fácil, não é?
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
fonte
fonte
utf8EncodedXml
é UTF-16.Respostas:
Seu código não coloca o UTF-8 na memória conforme você o lê em uma string novamente, então não está mais em UTF-8, mas em UTF-16 (embora idealmente seja melhor considerar strings em um nível superior qualquer codificação, exceto quando forçado a fazê-lo).
Para obter os octetos UTF-8 reais que você pode usar:
Eu deixei de fora a mesma disposição que você deixou. Sou ligeiramente favorável ao seguinte (com o descarte normal deixado):
O que é quase a mesma quantidade de complexidade, mas mostra que em cada estágio há uma escolha razoável para fazer outra coisa, a mais urgente delas é serializar para algum lugar diferente da memória, como um arquivo, TCP / IP stream, banco de dados, etc. Resumindo, não é tão prolixo.
fonte
XmlWriter.Create(memoryStream, new XmlWriterSettings { Encoding = new UTF8Encoding(false) })
.Não, você pode usar um
StringWriter
para se livrar do intermediárioMemoryStream
. No entanto, para forçá-lo em XML, você precisa usar umStringWriter
que substitui aEncoding
propriedade:Ou se ainda não estiver usando o C # 6:
Então:
Obviamente, você pode fazer
Utf8StringWriter
em uma classe mais geral que aceita qualquer codificação em seu construtor - mas na minha experiência UTF-8 é de longe a codificação "personalizada" mais comumente necessária para umStringWriter
:)Agora, como Jon Hanna disse, isso ainda será UTF-16 internamente, mas provavelmente você vai passá-lo para outra pessoa em algum ponto, para convertê-lo em dados binários ... nesse ponto, você pode usar a string acima, converta-o em bytes UTF-8 e tudo ficará bem - porque a declaração XML especificará "utf-8" como a codificação.
EDIT: Um exemplo curto, mas completo para mostrar isso funcionando:
Resultado:
Observe a codificação declarada de "utf-8" que é o que queríamos, eu acredito.
fonte
TextWriter.Encoding
propriedade é usada pelo serializador XML para determinar qual nome de codificação especificar no próprio documento.XmlWriter
faça isso com o método de fábrica que pega umXmlWriterSettings
objeto e tem aOmitXmlDeclaration
propriedade definida comotrue
.Utf8StringWriter
solução é extremamente agradável e limpaMuito boa resposta usando herança, apenas lembre-se de substituir o inicializador
fonte
Achei esta postagem do blog que explica o problema muito bem e define algumas soluções diferentes:
(link morto removido)
Eu me conformei com a ideia de que a melhor maneira de fazer isso é omitir completamente a declaração XML quando estiver na memória. Na verdade, é UTF-16 nesse ponto de qualquer maneira, mas a declaração XML não parece significativa até que tenha sido gravada em um arquivo com uma codificação específica; e mesmo assim a declaração não é necessária. Não parece interromper a desserialização, pelo menos.
Como @Jon Hanna menciona, isso pode ser feito com um XmlWriter criado assim:
fonte