La sérialisation XML avec XmlWriter via StringBuilder est l'utf-16, tandis que via le Flux est en utf-8?
J'ai été surpris quand je l'ai rencontrée, et a écrit une application console pour vérifier et s'assurer que je ne faisais rien d'autre.
Quelqu'un peut-il m'expliquer cela?
Voici le code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
var o = new SomeObject { Field1 = "string value", Field2 = 8 };
Console.WriteLine("ObjectToXmlViaStringBuilder");
Console.Write(ObjectToXmlViaStringBuilder(o));
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("ObjectToXmlViaStream");
Console.Write(StreamToString(ObjectToXmlViaStream(o)));
Console.ReadKey();
}
public static string ObjectToXmlViaStringBuilder(SomeObject someObject)
{
var output = new StringBuilder();
var settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true };
using (var xmlWriter = XmlWriter.Create(output, settings))
{
var serializer = new XmlSerializer(typeof(SomeObject));
var namespaces = new XmlSerializerNamespaces();
xmlWriter.WriteStartDocument();
xmlWriter.WriteDocType("Field1", null, "someObject.dtd", null);
namespaces.Add(string.Empty, string.Empty);
serializer.Serialize(xmlWriter, someObject, namespaces);
}
return output.ToString();
}
private static string StreamToString(Stream stream)
{
var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
public static Stream ObjectToXmlViaStream(SomeObject someObject)
{
var output = new MemoryStream();
var settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true };
using (var xmlWriter = XmlWriter.Create(output, settings))
{
var serializer = new XmlSerializer(typeof(SomeObject));
var namespaces = new XmlSerializerNamespaces();
xmlWriter.WriteStartDocument();
xmlWriter.WriteDocType("Field1", null, "someObject.dtd", null);
namespaces.Add(string.Empty, string.Empty);
serializer.Serialize(xmlWriter, someObject, namespaces);
}
output.Seek(0L, SeekOrigin.Begin);
return output;
}
public class SomeObject
{
public string Field1 { get; set; }
public int Field2 { get; set; }
}
}
}
C'est le résultat:
ObjectToXmlViaStringBuilder
<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE Field1 SYSTEM "someObject.dtd">
<SomeObject>
<Field1>string value</Field1>
<Field2>8</Field2>
</SomeObject>
ObjectToXmlViaStream
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Field1 SYSTEM "someObject.dtd">
<SomeObject>
<Field1>string value</Field1>
<Field2>8</Field2>
</SomeObject>
Vous devez vous connecter pour publier un commentaire.
Lorsque vous créez un
XmlWriter
autour d'unTextWriter
, leXmlWriter
toujours utilise l'encodage de la sous-jacentesTextWriter
. L'encodage d'unStringWriter
est toujours UTF-16, puisque c'est comme ça .NET les chaînes de caractères sont codés en interne.Lorsque vous créez un
XmlWriter
autour d'unStream
, il n'y a pas de codage définies pour leStream
, de sorte qu'il utilise l'encodage spécifié dans laXmlWriterSettings
.La solution la plus élégante pour moi est d'écrire à un memorystream, puis en utilisant le codage pour coder le flux de tout codage est nécessaire.
comme
où l'encodage prend place à ....l'encodage.GetString(memS.ToArray())...
Si possible, le XmlWriter utilise l'encodage du flux sous-jacent. Il a écrit des données UTF-8 à un flux, il savait UTF-16, vous aimeriez retrouver avec un désordre. Écrit les données UTF-16 pour un UTF-8 flux provoque également des problèmes, en particulier pour les environnements qui utilisent les chaînes vides (comme le C/C++).
Le StringBuilder/StringWriter présente un UTF-16 en continu à l'XmlWriter, de sorte que le XmlWriter ignore votre demande de réglage et l'utilise.
Dans la pratique, j'ai l'habitude de ne pas émettre de l'en-tête, de cette façon je peux utiliser un StringBuilder dessous et enregistrer quelques lignes de code vous embêter avec commutation de codages.
Stream
n'a pas d'encodage, c'est juste des données binaires brutes... Mais leTextWriter
utilisé pour écrire dans le flux t ont un codage.