BOM的介紹
在github上寫md文件的時候,發現生成自己blog時,報出一個錯誤是讓使用UTF-8編碼,然后在Notepad++上把文件轉成UTF-8時,發現菜單中有"UTF-8無BOM編碼格式"。
上網查了一下BOM的定義:byte order mark
這個是為UTF-16和UTF-32准備的,用於標記字節序(byte order)。
「UTF-8」和「帶 BOM 的 UTF-8」的區別就是有沒有 BOM。即文件開頭有沒有 U+FEFF。
BOM的愛恨情仇
知乎上有個比較好的文章,講了BOM問題,下面直接引用了原文:
作者:陳甫鵃
鏈接:https://www.zhihu.com/question/20167122/answer/14199022
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
首先,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。如有高手解答不勝感激。
@引用結束
總結
以下是一些經典語錄:
- 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——為了讓它們的上古程序能繼續運行下去,這個各自有自己利益訴求的差異決定其實並不對錯
參考: