XmlWriterSettings.Encoding 設定無效

最近在寫一個比較方便使用的工具方法來做 XML 的序列化的時候, 發生了一個神奇的問題, XmlWriterSettings.Encoding 預設應該是 UTF-8, 但是轉出來的 XML 卻是 UTF-16, 這就奇了怪了…

XmlWriterSettings.Encoding 設定無效

先來看下面這段 Demo

1
2
3
4
5
6
7
8
9
10
11
12
private static string DemoForFailure()
{
var xmlWriterSettings = new XmlWriterSettings();

var sb = new StringBuilder();

using (var xmlWriter = XmlWriter.Create(sb, xmlWriterSettings))
{
new XmlSerializer(typeof(string)).Serialize(xmlWriter, string.Empty);
return sb.ToString();
}
}

程式碼就是很簡單的把一個空字串拿去序列化, 但是輸出的字串卻是 <?xml version="1.0" encoding="utf-16"?><string />, 即使特別再手動設定 Encoding 也是一樣, 如: var xmlWriterSettings = new XmlWriterSettings() { Encoding = Encoding.UTF8 };

稍微推敲一下程式碼, 猜測應該是 StringBulider 的問題, 可能是因為 StringBulider 操作字串有自己的 Encoding, 所以就往這方面去找.

原因

因為今天比較懶不想自己往底部去鑽, 所以先問問 google 大神先, 也是運氣好還真的有找到一篇分析文, 大意上就是 StringBuilder 設計上是直接操作字元而不是 bytes, 而字串在 .NET 裡面都是 UTF-16 編碼的.

解法

所以這邊改用存取 Stream 的方式來操作, 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
private static string DemoForSuccess()
{
var xmlWriterSettings = new XmlWriterSettings() { Encoding = Encoding.UTF8 };

using (var ms = new MemoryStream())
using (var sr = new StreamReader(ms))
using (var xmlWriter = XmlWriter.Create(ms, xmlWriterSettings))
{
new XmlSerializer(typeof(string)).Serialize(xmlWriter, string.Empty);
ms.Position = 0;
return sr.ReadToEnd();
}
}

結論

也沒什麼特別的技巧好結論, 特別寫出來只是怕之後忘記, 再遇到還要再踩一次.

參考

XmlWriterSettings Encoding Being Ignored?