L'élimination correcte des objets a été supprimée pour des raisons de brièveté, mais je suis choqué si c'est le moyen le plus simple d'encoder un objet en UTF-8 en mémoire. Il doit y avoir un moyen plus simple, n'est-ce pas?
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
la source
la source
utf8EncodedXml
comme UTF-16.Réponses:
Votre code n'obtient pas l'UTF-8 en mémoire lorsque vous le relisez à nouveau dans une chaîne, donc ce n'est plus en UTF-8, mais en UTF-16 (bien que, idéalement, il soit préférable de considérer les chaînes à un niveau supérieur à tout encodage, sauf lorsque cela est forcé).
Pour obtenir les octets UTF-8 réels, vous pouvez utiliser:
J'ai laissé de côté la même disposition que vous avez laissée. Je préfère légèrement ce qui suit (avec une élimination normale laissée):
Ce qui est à peu près le même niveau de complexité, mais montre qu'à chaque étape, il y a un choix raisonnable de faire autre chose, dont le plus urgent est de sérialiser vers un endroit autre que la mémoire, comme un fichier, TCP / IP flux, base de données, etc. Dans l'ensemble, ce n'est pas vraiment bavard.
la source
XmlWriter.Create(memoryStream, new XmlWriterSettings { Encoding = new UTF8Encoding(false) })
.Non, vous pouvez utiliser a
StringWriter
pour vous débarrasser de l'intermédiaireMemoryStream
. Cependant, pour le forcer en XML, vous devez utiliser unStringWriter
qui remplace laEncoding
propriété:Ou si vous n'utilisez pas encore C # 6:
Ensuite:
De toute évidence, vous pouvez créer
Utf8StringWriter
une classe plus générale qui accepte n'importe quel encodage dans son constructeur - mais d'après mon expérience, UTF-8 est de loin l'encodage "personnalisé" le plus couramment requis pour unStringWriter
:)Maintenant, comme le dit Jon Hanna, ce sera toujours UTF-16 en interne, mais vous allez probablement le passer à autre chose à un moment donné, pour le convertir en données binaires ... à ce stade, vous pouvez utiliser la chaîne ci-dessus, convertissez-le en octets UTF-8, et tout ira bien - car la déclaration XML spécifiera "utf-8" comme encodage.
EDIT: Un exemple court mais complet pour montrer ce fonctionnement:
Résultat:
Notez l'encodage déclaré de "utf-8" qui est ce que nous voulions, je crois.
la source
TextWriter.Encoding
propriété est utilisée par le sérialiseur XML pour déterminer le nom de codage à spécifier dans le document lui-même.XmlWriter
faites-le avec la méthode de fabrique qui prend unXmlWriterSettings
objet et que laOmitXmlDeclaration
propriété est définie surtrue
.Utf8StringWriter
solution est extrêmement belle et propreTrès bonne réponse utilisant l'héritage, n'oubliez pas de remplacer l'initialiseur
la source
J'ai trouvé ce billet de blog qui explique très bien le problème, et définit quelques solutions différentes:
(lien mort supprimé)
J'ai opté pour l'idée que la meilleure façon de le faire est d'omettre complètement la déclaration XML lorsqu'elle est en mémoire. C'est en fait UTF-16 à ce stade de toute façon, mais la déclaration XML ne semble pas significative tant qu'elle n'a pas été écrite dans un fichier avec un codage particulier; et même alors, la déclaration n'est pas requise. Cela ne semble pas casser la désérialisation, au moins.
Comme le mentionne @Jon Hanna, cela peut être fait avec un XmlWriter créé comme ceci:
la source