UTF-8的BOM之爭

BOM的介紹

在github上寫md文件的時候,發現生成本身blog時,報出一個錯誤是讓使用UTF-8編碼,而後在Notepad++上把文件轉成UTF-8時,發現菜單中有"UTF-8無BOM編碼格式"。linux

上網查了一下BOM的定義:byte order mark 這個是爲UTF-16和UTF-32準備的,用於標記字節序(byte order)。git

「UTF-8」和「帶 BOM 的 UTF-8」的區別就是有沒有 BOM。即文件開頭有沒有 U+FEFF。程序員

BOM的愛恨情仇

知乎上有個比較好的文章,講了BOM問題,下面直接引用了原文:github

做者:陳甫鵃 連接:https://www.zhihu.com/question/20167122/answer/14199022 來源:知乎 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。mongodb

首先,BOM是啥。這個就不解釋了,Wikipedia上很詳細。http://en.wikipedia.org/wiki/Byte_order_mark。在網頁上使用BOM是個錯誤。BOM設計出來不是用來支持HTML和XML的。要識別文本編碼,HTML有charset屬性,XML有encoding屬性,不必拉BOM撐場面。雖然理論上BOM能夠用來識別UTF-16編碼的HTML頁面,但實際工程上不多有人這麼幹。畢竟UTF-16這種編碼連ASCII都雙字節,實在不適用於作網頁。其實說BOM是個壞習慣也不盡然。BOM也是Unicode標準的一部分,有它特定的適用範圍。一般BOM是用來標示Unicode純文本字節流的,用來提供一種方便的方法讓文本處理程序識別讀入的.txt文件是哪一個Unicode編碼(UTF-8,UTF-16BE,UTF-16LE)。Windows相對對BOM處理比較好,是由於Windows把Unicode識別代碼集成進了API裏,主要是CreateFile()。打開文本文件時它會自動識別並剔除BOM。Windows用這個有歷史緣由,由於它最初脫胎於多代碼頁的環境。而引入Unicode時Windows的設計者又但願能在用戶不注意的狀況下同時兼容Unicode和非Unicode(Multiple byte)文本文件,就只能藉助這種小trick了。相比之下,Linux這樣的系統在多locale的環境中浸染的時間比較短,再加上社區自己也有足夠的動力輕裝前進(吐槽:微軟對兼容性的要求確實是到了很是偏執的地步,任何一點破壞兼容性的作法都不容許,以致於不少時候是本身綁住本身的雙手),因此乾脆一步到位進入UTF-8。固然中間其實有一段過渡期,好比從最初全UTF-8的GTK+2.0發佈到基本上全部GTK開發者都棄用多locale的GTK+1.2,我印象中至少經歷了三到四年。BOM不受歡迎主要是在UNIX環境下,由於不少UNIX程序不鳥BOM。主要問題出在UNIX那個全部腳本語言通行的首行#!標示,這東西依賴於shell解析,而不少shell出於兼容的考慮不檢測BOM,因此加進BOM時shell會把它解釋爲某個普通字符輸入致使破壞#!標示,這就麻煩了。其實不少現代腳本語言,好比Python,其解釋器自己都是能處理BOM的,可是shell卡在這裏,沒辦法,只能躺着也中槍。提及來這也不能怪shell,由於BOM自己違反了一個UNIX設計的常見原則,就是文檔中存在的數據必須可見。BOM不能做爲可見字符被文本編輯器編輯,就這一條不少UNIX開發者就不滿意。順便說一句,即便腳本語言能處理BOM,隨處使用BOM也不是推薦的辦法。各個腳本語言對Unicode的處理都有本身的一套,Python的 # -- coding: utf-8 --,Perl的use utf8,都比BOM簡單並且可靠。另外一個好消息是,即便是必須在Windows和UNIX之間切換的朋友也不會悲催。幸好在UNIX環境下咱們還有VIM這種神器,即便遇到BOM擋道,咱們也能夠經過 set nobomb; set fileencoding=utf8; w 三條命令解決問題。最後回頭想一想,彷佛也真就只有Windows堅持用BOM了。P.S.:本問題是本身的第150個回答。忽然發現本身回答得不多不多⋯⋯P.S. 2:忽然想起須要解釋一下爲何說VIM去除bomb的操做須要在UNIX下完成。由於VIM在Windows環境下有一個奇怪的bug,老是把UTF-16文件識別成二進制文件,而UNIX(Linux或者Mac均可以)下VIM則無問題。這個問題從VIM 6.8一直跟着我到VIM 7.3。目前尚不清楚這是VIM的bug仍是我本身那個.vimrc文件的bug。若有高手解答不勝感激。shell

@引用結束vim

總結

如下是一些經典語錄:windows

  • HTML有charset屬性,XML有encoding屬性,不必拉BOM撐場面
  • UTF-16這種編碼連ASCII都雙字節,實在不適用於作網頁
  • 一般BOM是用來標示Unicode純文本字節流的,讓文本處理程序識別txt文件是哪一個Unicode編碼(UTF-8,UTF-16BE,UTF-16LE)
  • Windows相對對BOM處理比較好, 打開文本文件時它會自動識別並剔除BOM.
  • Windows的設計者但願能在用戶不注意的狀況下同時兼容Unicode和非Unicode(Multiple byte)文本文件.
  • Linux一步到位進入UTF-8, 過渡期至少經歷了三到四年.
  • BOM不受歡迎主要是在UNIX環境下,由於不少UNIX程序不鳥BOM。由於BOM自己違反了一個UNIX設計的常見原則,就是文檔中存在的數據必須可見。
  • UNIX環境下咱們還有VIM這種神器,即便遇到BOM擋道,咱們也能夠經過 set nobomb; set fileencoding=utf8; w 三條命令解決問題。
  • 彷佛也真就只有Windows堅持用BOM了。
  • UTF-8不須要BOM, 因此不含BOM的UTF-8纔是標準形式.
  • 微軟在 UTF-8 中使用 BOM 是由於這樣能夠把 UTF-8 和 ASCII 等編碼明確區分開
  • UTF-8 的網頁代碼不該使用 BOM,不然經常會出錯
  • 寫C++代碼建議程序要在windows 和 mac 還有linux 上運行的話,源代碼最好保存成utf-8 帶bom的格式,這樣比較通用一些。而用utf-16 不管大端仍是小端,g++ 都不認的。或者用utf-8 不帶bom格式,而後代碼不要出現非ascii 127之後的字符。
  • 帶用bom的utf-8也是符合國際標準的
  • 微軟在堅持使用bom上沒有錯,由於這是在爲用戶考慮的。也許給咱們這些寫程序的帶來了不便,可是,計算機最普遍的用戶不是程序員。
  • 帶頭的鵝和去頭的鵝,有些編輯器比較傻會把去頭的鵝認成鴨子
  • 以UTF-8格式編碼, 從notepad++ --> Mongodb裏面複製東西的時候,莫名其妙多了很多的字節數。若是不安裝notepad++,使用默認的記事本,那就更是個坑,默認有bom,你還沒法選擇。
  • 就是由於這個bom,CSV導入mongodb時,第一個字段老是不正常,直接致使用第一個字段做爲條件find時,出不告終果!
  • utf8對ascii的兼容確實是它的好,可是這個優勢在某些時候偏偏成了隱藏問題的缺點。所以bom大法好,加bom保平安.
  • 爲何windows的記事本要強行給utf8加bom的緣由——爲了兼容舊系統的編碼問題,unix陣營放棄帶bom的utf8——爲了讓它們的上古程序能繼續運行下去,這個各自有本身利益訴求的差別決定其實並不對錯

參考:編輯器

相關文章
相關標籤/搜索