2012-02-27 17 views
20

mam tę metodę rozszerzeniaDlaczego XmlWriter zawsze generuje kodowanie utf-16?

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(); 
     } 
    } 

ale ilekroć ja nazywam to, że ma kodowanie utf-16 określony, tj <?xml version="1.0" encoding="utf-16"?>. Co ja robię źle?

+0

możliwe duplikat [Jak umieścić atrybut kodowania do formatu XML inny, że UTF-16 z XmlWriter?] (Http://stackoverflow.com/questions/427725/ how-to-put-an-encoding-attribute-to-xml-other-that-utf-16-with-xmlwriter) –

+0

Zdałem sobie sprawę, że to jest dupe, więc głosuj na zamknięcie –

Odpowiedz

10

Łańcuchy są UTF-16, więc zapis do StringWriter zawsze będzie używał UTF-16. Jeśli nie tego chcesz, użyj innej klasy pochodnej TextWriter z kodowaniem, które ci się podoba.

+1

Potrząsa głową. Więc jaki jest sens posiadania właściwości kodowania w XmlWriterSettings. Tak, ciąg znaków to UTF-16, ale jeśli serializujemy ciąg znaków, ponieważ chcemy pisać do pliku lub czegoś, a chcemy, aby atrybut kodowania deklaracji xml pasował do rzeczywistego kodowania pliku, który tworzyć, a jest mało prawdopodobne, aby był to UTF-16. – bbsimonbb

+0

@User nie serializuje do ciągu znaków, przejdź bezpośrednio do strumienia. –

+0

OK. To ma więcej sensu. – bbsimonbb

14

O ile mi wiadomo, klasa StringWriter zawsze będzie używać kodowania UTF 16 podczas serializowania do łańcucha. Możesz napisać własną klasę override który akceptuje innego kodowania:

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; } 
    } 
} 

Więc można użyć zamiast tego:

using(var stringWriter = new StringWriterWithEncoding(Encoding.UTF8)) 
{ 
    ... 
} 
+0

Big +1, działa dobrze , Dziękuję Ci. –

1

Należy czerpać nową klasę z StringWriter który ma nadpisane własność kodowania.

1

Zgodnie z zaakceptowaną odpowiedzią, StringWriter jest domyślnie UTF-16 (Unicode) i konstrukcja. Jeśli chcesz to zrobić, uzyskując ciąg znaków UTF-8 na końcu, możesz to zrobić na dwa sposoby:

Rozwiązanie nr 1 (niezbyt wydajna, zła praktyka, ale dostaje pracę done): Zrzuć go do pliku tekstowego i wczytaj ponownie, usuń plik (prawdopodobnie tylko dla małych plików, jeśli nawet chcesz to zrobić - po prostu chciałeś pokazać, że to może być zrobione!)

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 xmlWriter = XmlWriter.Create("MyFile.xml", settings)) 
    { 
     serializer.Serialize(xmlWriter, value); 
    } 

    XmlDocument xml = new XmlDocument(); 
    xml.Load("MyFile.xml"); 
    byte[] bytes = Encoding.UTF8.GetBytes(xml.OuterXml);   
    File.Delete("MyFile.xml"); 

    return Encoding.UTF8.GetString(bytes); 

} 

rozwiązanie nr 2 (lepiej, łatwiej, bardziej eleganckie rozwiązanie!): Zrób to jak masz to, za pomocą StringWriter, ale używać jej Encoding właściwość, aby ustawić go na UTF-8

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(Encoding.UTF8)) 
    { 
     using(var xmlWriter = XmlWriter.Create(stringWriter, settings)) 
     { 
      serializer.Serialize(xmlWriter, value); 
     } 

     return stringWriter.ToString(); 
    } 
} 
+0

Czy tu czegoś brakuje? ' StringWriter' nie wydaje się przyjmować właściwości Kodowania jako argumentu konstruktora. – crush