web-dev-qa-db-fra.com

Pourquoi XmlWriter génère-t-il toujours le codage utf-16?

J'ai cette méthode d'extension

    public static string SerializeObject<T>(this T value)
    {
        var serializer = new XmlSerializer(typeof(T));           
        var settings = new XmlWriterSettings
                       {
                        Encoding = new UTF8Encoding(true), 
                        Indent = false, 
                        OmitXmlDeclaration = false,
                        NewLineHandling = NewLineHandling.None
                       };

        using(var stringWriter = new StringWriter()) 
        {
            using(var xmlWriter = XmlWriter.Create(stringWriter, settings)) 
            {
                serializer.Serialize(xmlWriter, value);
            }

            return stringWriter.ToString();
        }
    }

mais chaque fois que j'appelle cela, il a un encodage de utf-16 spécifié, c'est-à-dire <?xml version="1.0" encoding="utf-16"?>. Qu'est-ce que je fais mal?

25
Glenn Slaven

Les chaînes étant au format UTF-16, l'écriture sur un StringWriter utilisera toujours le format UTF-16. Si ce n'est pas ce que vous voulez, utilisez une autre classe dérivée TextWriter avec le codage souhaité.

14
John Saunders

Autant que je sache, la classe StringWriter utilisera toujours le codage UTF 16 lors de la sérialisation en chaîne. Vous pouvez écrire votre propre classe de remplacement qui accepte un codage différent:

public class StringWriterWithEncoding : StringWriter
{
    private readonly Encoding _encoding;

    public StringWriterWithEncoding()
    {
    }

    public StringWriterWithEncoding(IFormatProvider formatProvider)
        : base(formatProvider)
    {
    }

    public StringWriterWithEncoding(StringBuilder sb)
        : base(sb)
    {
    }

    public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider)
        : base(sb, formatProvider)
    {
    }


    public StringWriterWithEncoding(Encoding encoding)
    {
        _encoding = encoding;
    }

    public StringWriterWithEncoding(IFormatProvider formatProvider, Encoding encoding)
        : base(formatProvider)
    {
        _encoding = encoding;
    }

    public StringWriterWithEncoding(StringBuilder sb, Encoding encoding)
        : base(sb)
    {
        _encoding = encoding;
    }

    public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider, Encoding encoding)
        : base(sb, formatProvider)
    {
        _encoding = encoding;
    }

    public override Encoding Encoding
    {
        get { return (null == _encoding) ? base.Encoding : _encoding; }
    }
}

Vous pouvez donc utiliser ceci à la place:

using(var stringWriter = new StringWriterWithEncoding( Encoding.UTF8))
{
   ...
}
15
Bojin Li

Vous devriez dériver une nouvelle classe de StringWriter qui possède une propriété de codage remplacée.

1
Ahmet B. Badın

Si vous ne souhaitez pas utiliser une classe dérivée de StringWriter, vous pouvez simplement définir OmitXmlDeclaration sur false et déclarer votre classe, comme je le fais ci-dessous:

 public static string Serialize<T>(this T value, string xmlDeclaration = "<?xml version=\"1.0\"?>") where T : class, new()
        {
            if (value == null) return string.Empty;

            using (var stringWriter = new StringWriter())
            {
                var settings = new XmlWriterSettings
                {
                    Indent = true,
                    OmitXmlDeclaration = xmlDeclaration != null,
                };

                using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
                {
                    var xmlSerializer = new XmlSerializer(typeof(T));

                    xmlSerializer.Serialize(xmlWriter, value);

                    var sb = new StringBuilder($"{Environment.NewLine}{stringWriter}");

                    sb.Insert(0, xmlDeclaration);

                    return sb.ToString();
                }
            }
0
CarneyCode