UTF8編碼問題

UTF8最好不要帶BOM,附許多經典評論

UTF-8 不需要 BOM,儘管 Unicode 標準允許在 UTF-8 中使用 BOM。
所以不含 BOM 的 UTF-8 纔是標準形式,在 UTF-8 文件中放置 BOM 主要是微軟的習慣(順便提一下:把帶有 BOM 的小端序 UTF-16 稱作「Unicode」而又不詳細說明,這也是微軟的習慣)。
BOM(byte order mark)是爲 UTF-16 和 UTF-32 準備的,用於標記字節序(byte order)微軟在 UTF-8 中使用 BOM 是因爲這樣可以把 UTF-8 和 ASCII 等編碼明確區分開,但這樣的文件在 Windows 之外的操作系統裏會帶來問題。

「UTF-8」和「帶 BOM 的 UTF-8」的區別就是有沒有 BOM。即文件開頭有沒有 U+FEFF。
UTF-8 的網頁代碼不應使用 BOM,否則常常會出錯。這是一個小例子: 爲什麼這個網頁代碼 <head> 內的信息會被瀏覽器理解爲在 <body> 內?

另附《The Unicode Standard, Version 6.0》之 3.10 D95 UTF-8 encoding scheme 的一段話:
While there is obviously no need for a byte order signature when using UTF-8, there are occasions when processes convert UTF-16 or UTF-32 data containing a byte order mark into UTF-8. When represented in UTF-8, the byte order mark turns into the byte sequence. Its usage at the beginning of a UTF-8 data stream is neither required nor recommended by the Unicode Standard, but its presence does not affect conformance to the UTF-8 encoding scheme. Identification of the byte sequence at the beginning of a data stream can, however, be taken as a near-certain indication that the data stream is using the UTF-8 encoding scheme.
http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf

---------------------------------------------------------
首先,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用這個有歷史原因,因爲它最初脫胎於多代碼頁的環境(ANSI環境)。而引入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。如有高手解答不勝感激。

---------------------------------------------------------

有bom格式在開頭會多出3個字節 EF BB BF ,主要用於識別編碼。bom應該是windows特有的,在製作網頁時會產生各種意想不到的問題,例如多輸出了一個空行,影響PHP的session或者cookies功能(出現 header already sent錯誤),甚至可能引起頁面的亂碼(那3個字節影響了瀏覽器對頁面編碼的處理),因此總是推薦使用無bom編碼。爲了處理這個問題我甚至寫了一個批量處理的PHP腳本。

---------------------------------------------------------
邸強,軟件開發ing
張旭東、Mingyue Zhou、sapjax 贊同
幾周前還在爲BOM的問題苦惱着。。。
正如@樑海所說,“不含 BOM 的 UTF-8 纔是標準形式”,的確是這樣,無BOM使用得更多些,所以個人還是推薦一般情況下用無BOM的形式吧,除非有問題的時候,再考慮換有BOM的。Windows系統保存的都是有BOM的,所以你可以看到,用記事本保存一個UTF-8的txt,其實是有BOM的,這一點需要注意。另外不同的文本編輯器對於有無BOM的稱呼也略有不同,比如EditPlus,有BOM的稱爲UTF-8+,無BOM的稱爲UTF-8,而在Notepad++中,有BOM的被稱爲標準UTF-8,而無BOM則被稱爲UTF-8無BOM。

---------------------------------------------------------
武龍飛,c/c++ 程序員,喜歡天文學,數學和心理學。
Weijing Huang、Bill Chan、icky R 贊同
以下文字出自我的博客內容,從另一面解說不一樣的bom。
---------------------------------------------------------
字符編碼相信是每個程序員的噩夢,只要是有中文的地方,總是會遇到各種編碼的問題,並且這種問題還非常難纏,尤其在linux上,因爲上面很多軟件都是針對英語國家開發的,是不會考慮其他語種編碼問題。在遇到編碼的無數大坑之後,我決定仔細研究下編碼問題,因爲這就像一道坎一直橫在你面前,每次到這裏你都會跌到,每次爬起來之後,你都若無其事,這樣的人被稱作戰士,真正的戰士。可惜是個力量戰士,做爲新時代的智力戰士,當然不能在那跌到然後又在這繼續跌到。
文件的存儲方式:
文件都有自己的存儲格式,比如最常見的txt,cpp,h,c,xml ,png, rmvb各種格式,還有自定義格式。這些文件不論是什麼格式,都是存儲在計算機硬盤裏的2進制格存儲,對應不同文件格式,有不同的軟件解析。這篇文章不談文件是如何存儲的,只談文件是如何解析的。
文本文件解析:
文本文件對應於人類可以閱讀的文本,如何從2進制轉換爲文本文件呢?起初由於計算機在美國發明,自然大家考慮的是英語如何表示,英語字母總共26個,加上特殊字符,128個字符,7位既一個byte即可表示出來。這個就是大家所熟知的ascill編碼。對應關係很簡單,一個字符對應一一個byte。
但很快發現,其他非英語國家的文字遠遠超過ascill碼,這時候大家當然想統一一下,不同國家出了自己不同的編碼方式,中國的gb2312就是自己做出來的編碼方式,這樣下去每個國家都有自己的編碼方式,來回轉換太麻煩了。這時候出現了新的編碼方式,unicode編碼方式,想將編碼統一,所以規定了每個字符對應的unicode碼。
1、很多文件都是ascii編碼,如果用unicode 太浪費。
2、沒有標誌位說明該幾個字節來解析爲一個符號。
這時候拯救世界的utf出現了,utf是unicode的一種實現,只不過更聰明瞭。utf16是佔用兩字節,或者四字節,utf32是佔用四字節。utf8是很聰明的一種表示方式。
1、對於單字節符號,字節第一位爲0,後面7位表示字節編碼。
2、對於n字節符號,第一字節的前n位都設爲1,第n+1位爲0,其餘位位編碼位置。
對於不同的編碼,在文本的最前方有不同的標誌,unicode 通常有兩位來表示分別是ff fe, 或者feff, fffe表示big-endian 編碼feff表示litte-endian編碼。utf8是efbbbf來開頭的。可以看出來utf-8是自解釋的,所以不用帶這個標誌文件,大多數程序是可以識別的。但有些程序不能識別這個標誌,比如php就會直接把這個標誌當文本解析,不會忽略。相信很多遇到php輸出文本解析亂碼或者解析錯誤的同學都遇到這樣的問題。
最後說說如何去掉或者加上bom,如果有vim那最好不過了,去掉命令:
set encoding=utf-8
set nobomb
添加命令:
set encoding=utf-8
set bomb
---------------------------------------------------------
帶 BOM 的 UTF-8 就是赤裸裸的流氓!!!!!!!!!

windows總是自做聰明的做一些別人無法理解的事情!!!UTF-8是不需要BOM頭的~~~!!

從剛開始學習代碼(實在不能稱我做的東西爲程序)到現在,不曉得被這個BOM頭搞了多少次,特別是對於我這種完全自學的人,知道找一個BUG需要多久多久不????

帶不帶BOM頭區別就在於這個BOM頭,祥見排名靠前的大神答案。windows特有的奇葩。請使用UTF-8 不帶BOM頭!!

它產生的BUG包含但不僅限於:
鍩 -- 感謝 @飛揚 提供,參考其答案
HTML空白行
div之間莫明的間隔
亂碼!
如果你用ssl那麼一定會有問題!!!

順便再鄙視一下 SONY的記憶棒、IPHONE的接口~~

這種吐槽的東西就讓它摺疊吧
--------------------------------------------------------
帶 BOM 的 UTF-8 非常操蛋,經常造成莫名其妙的問題。
---------------------------------------------------------
我都是用的UTF-8 without BOM,帶BOM的經常出現亂碼
---------------------------------------------------------
notepad++會自動添加爲帶Bom的utf8比較坑爹
---------------------------------------------------------
建議編程人員能使用 Mac 編程的儘量使用Mac,Window是及其操蛋的操作系統。其次,如果我們要讀取三方的文件並以UTF-8格式解析的時候一定要注意去判斷這個文件是否有BOM,例如:sql文件的解析執行。
---------------------------------------------------------
網頁編程中用不用bom我就不說什麼了,因爲軟件原因無法使用的就更不能用了。

最近在學習用cocos2d-x,純C++的編碼,如果代碼中有中文等的非ascii字符出現。發現會出錯。代碼是在mac 下用xcode 寫的,放到windows 下用vs 編譯。
最後把所有的源文件轉成了帶bom的格式後編譯通過了,鏈接失敗,這想這個就不是編碼的問題了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章