私はこの拡張メソッドを持っています
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();
}
}
しかし、これを呼び出すときはいつでも、utf-16
のエンコーディングが指定されています。つまり、<?xml version="1.0" encoding="utf-16"?>
です。私は何が間違っているのですか?
文字列はUTF-16であるため、StringWriterへの書き込みには常にUTF-16が使用されます。それが希望どおりでない場合は、他のTextWriter
派生クラスを、好みのエンコーディングで使用してください。
私の知る限り、StringWriterクラスは、文字列にシリアル化するときに常にUTF16エンコーディングを使用します。別のエンコーディングを受け入れる独自のオーバーライドクラスを作成できます。
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; }
}
}
したがって、代わりにこれを使用できます。
using(var stringWriter = new StringWriterWithEncoding( Encoding.UTF8))
{
...
}
オーバーライドされたエンコーディングプロパティを持つStringWriterから新しいクラスを派生する必要があります。
@ john-saundersが彼の答えで述べたように:
StringWriterは常にUTF-16を使用します
そのため、この目的でMemoryStreamを使用しました。
私の場合、windows-1251エンコーディングを使用しています。
var xmlSstring = "";
using (var ms = new MemoryStream())
{
var encoding = Encoding.GetEncoding(1251);
var settings = new XmlWriterSettings
{
Indent = true,
Encoding = encoding
};
using (var xmlTextWriter = XmlWriter.Create(ms, settings))
{
doc.Save(xmlTextWriter);
xmlString = encoding.GetString(ms.ToArray());
}
}
StringWriter
から派生したクラスを使用したくない場合は、私と同じように、OmitXmlDeclaration
をfalse
に設定して、独自のクラスを宣言できます。以下を実行してください:
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();
}
}
受け入れられた答えが言うように、StringWriter
はデフォルトで設計上UTF-16(Unicode)です。最後にUTF-8文字列を取得してそれを実行したい場合は、2つの方法で実行できます。
解決策#1(あまり効率的ではなく、悪い習慣ですが、仕事は終わります): それをテキストファイルにダンプして読み戻し、ファイルを削除します(おそらく、これを実行したい場合でも、小さなファイルにのみ適しています-実行できることを示したかっただけです!)
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);
}
解決策#2(より良く、より簡単で、よりエレガントな解決策!):StringWriter
を使用して、お持ちのように実行しますが、Encoding
プロパティを使用して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 UTF8StringWriter())
{
using(var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, value);
}
return stringWriter.ToString();
}
}
public class UTF8StringWriter : StringWriter
{
public override Encoding Encoding
{
get
{
return Encoding.UTF8;
}
}
}