惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Help Net Security
Help Net Security
G
Google Developers Blog
雷峰网
雷峰网
WordPress大学
WordPress大学
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Engineering at Meta
Engineering at Meta
Security Latest
Security Latest
T
Threat Research - Cisco Blogs
AWS News Blog
AWS News Blog
F
Full Disclosure
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Exploit Database - CXSecurity.com
J
Java Code Geeks
U
Unit 42
C
Cyber Attacks, Cyber Crime and Cyber Security
V
V2EX
C
Cisco Blogs
博客园 - 司徒正美
Project Zero
Project Zero
L
LINUX DO - 热门话题
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
Scott Helme
Scott Helme
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
S
Securelist
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
G
GRAHAM CLULEY
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyberwarzone
Cyberwarzone
MongoDB | Blog
MongoDB | Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
T
Threatpost
Recorded Future
Recorded Future
C
CXSECURITY Database RSS Feed - CXSecurity.com
宝玉的分享
宝玉的分享
N
News and Events Feed by Topic
人人都是产品经理
人人都是产品经理
The Register - Security
The Register - Security
S
Security Archives - TechRepublic
博客园 - Franky
N
News | PayPal Newsroom
Simon Willison's Weblog
Simon Willison's Weblog
S
SegmentFault 最新的问题
W
WeLiveSecurity
A
Arctic Wolf
B
Blog

博客园 - 黃偉榮

Web Project的檔案共用小技巧 IoC的中繼器:CommonServiceLocator Temporary Post Used For Theme Detection (d4b0aefa-c88e-4957-bba7-b367d1bfa042 - 3bfe001a-32de-4114-a6b4-4005b770f6d7) 寫CodedUI時如何尋找控制項的小技巧 Visual Studio 2010 Feature Packs 2之Silverlight自動化測試 Moles - Isolation framework for .NET(假.Net)介紹 [小技巧]Entity Framework強型別Include C#仿Oracle Decode,將ValueType對應成String - 黃偉榮 - 博客园 Visual Studio 單元測試的3種Initialize與Cleanup jQuery套件-檢查頁面的欄位是否有變更 用EventLogReader查詢特殊EventLog jQuery自製Plugin-Bind事件函式時檢查有沒有Bind過 ASP.NET MVC TempData使用心得 Visual Stuiod 自訂檔案比較合并工具 [小技巧]自動化測試時NLog的訊息輸出到測試結果中 小技巧:專案切換32與64位元組件 Linq小技巧:日期處理 Unit Test小技巧 : DateTime的Stub 解決TFS Build Asp.Net Mvc開啟MvcBuildViews後無法載入組件問題
UTF8Encoding與BOM
黃偉榮 · 2011-01-30 · via 博客园 - 黃偉榮

前陣子團隊中有用XmlSerializer將物件轉成XML存檔後,上傳給另一家公司,對方卻一直回報我們XML有問題,用文字編輯器看格式都很正確,但用XML的編輯器卻會出錯,發現原來是BOM害的。

用Visual Studio開啟,會出現未預期的XML宣告。XML宣告必須是文件中的第一個節點,前面不得有空白字元的錯誤訊息(如圖一),可是怎麼看都沒有多餘的空白,後來用2進元編輯器開啟,發現檔案前多了一組BOM(Byte order mark)。

2011-01-30_001222

圖一 用Visual Studio開啟檔案所發生的錯誤。

image

圖二 多出的BOM。

NOTE:什麼是BOM

位元組順序記號(byte-order mark,BOM),是Unicode存放在檔案的最前面,用來記錄讀位元組的順序,如UTF-8是EF BB BF,詳情請看:

維基百科 - 位元組順記號

維基百科 - 位元組序

這是其中的程式碼片段

var ser = new XmlSerializer(sample.GetType());
using (var memoryStream = new MemoryStream())
{
    //XmlSerializer不給Encoding,其XML宣告會是UTF-16
    var xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

    //空命名空間
    XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
    xsn.Add(String.Empty, String.Empty);

    ser.Serialize(xmlWriter, sample, xsn);
    var result = Encoding.UTF8.GetString(memoryStream.ToArray());

    //do something

    //把檔案存起來
    File.WriteAllText(filePath, result, Encoding.UTF8);
}

會照成輸入二次BOM的原因在於第5行與第17行,同時給了UTF8Encoding,但這不是最主要的原因,出錯的主因是二個地方都使用了有BOM的UTF8Encoding,查了MSDN,UTF8Encoding在建構式時,可以指定要不要輸出BOM,而System.Text.Encoding.UTF8是使用要輸出BOM的UTF8Encoding。

image

圖三 MSDN的UTF8Encoding的說明。

System.Text.Encoding.UTF8的原始碼

public static Encoding UTF8
{    
    get
    {
        if (utf8Encoding == null)
        {
            utf8Encoding = new UTF8Encoding(true);
        }
        return utf8Encoding;
    }
}

而System.Text.Encoding下的幾個靜態屬性UTF7、UTF8、Unicode、UTF32都是使用BOM為true的建構式,所以想不要BOM的話,請改用 new UTF8Encoding(false)

NOTE:

我同時也看了File.WriteAllText的原始碼,其實是我們雞婆,因為File.WriteAllText的多載,其中File.WriteAllText(string path, string contents),所用的預設Encoding就是new UTF8Encoding(false),所以我們不指定Encoding反而沒事。

參考資料

UTF8Encoding 類別