KB-UTF8Encoding And BOM

static void TestXMLWriter()
{
    MemoryStream ms = new MemoryStream();
    XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);
    xtw.Formatting = Formatting.Indented;
    XmlDocument xd = new XmlDocument();
    xd.LoadXml("<Group><User>Jeffrey</User></Group>");
    xd.Save(xtw);
    xtw.Flush();
    xtw.Close();
    string xml = Encoding.UTF8.GetString(ms.ToArray());
    Console.WriteLine(xml);
    xd.LoadXml(xml);
}

XmlTextWriter設為Fomatting.Indented時,可以把XML整成美美的縮排格式,於是我寫了以上的Code。但是這段程式有點問題,明明是XmlTextWriter輸出的Byte Array轉成字串後,再被另一個XmlDocument.LoadXml()卻會發生Data at the root level is invalid. Line 1, Position 1.的錯誤!

問題出在BOM!! Byte Order Mark,相信有很多人在使用文字編輯軟體都有發現Save UTF-8 with BOM這類的選項,BOM是加在文字檔前的幾個位元,可以協助應用程式識別文字的儲存格式(多用於Windows,許多被這幾個位元搞暈頭的開發者視之為微軟的餘毒),這裡有篇好文章

Byte order mark Description
EF BB BF UTF-8
FF FE UTF-16, little endian
FE FF UTF-16, big endian
FF FE 00 00 UTF-32, little endian
00 00 FE FF UTF-32, big-endian

先前的程式寫法,XmlTextWriter在寫入MemoryStream時,預設就會加上BOM。若我們將Byte Array寫入檔案,再用StreamReader或XmlDocument.Load讀取,BOM被用來識別編碼格式後將被丟棄不出現在內容字串中;當我們直接用Encoding.GetString轉成字串時,BOM則會被帶入,造成LoadXml()解析錯誤,雖可以設法Trim掉,但我覺得更好的方法是利用UTF8Encoding建構式所支援的encoderShouldEmitUTF8Identifier參數,設為false,輸出結果即不會加註BOM。因此程式要改成:

XmlTextWriter xtw = new XmlTextWriter(ms, new System.Text.UTF8Encoding(false));

That's all, folks.

歡迎推文分享:
Published 31 October 2007 12:39 AM 由 Jeffrey
Filed under: , ,
Views: 16,425



意見

沒有意見

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<October 2007>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication