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.
---------------------------------------------------------------------------------------------------------------------------
字符編碼相信是每一個程序員的噩夢,只要是有中文的地方,老是會遇到各類編碼的問題,而且這種問題還很是難纏,尤爲在linux上,由於上面不少軟件都是針對英語國家開發的,是不會考慮其餘語種編碼問題。在遇到編碼的無數大坑以後,我決定仔細研究下編碼問題,由於這就像一道坎一直橫在你面前,每次到這裏你都會跌到,每次爬起來以後,你都若無其事,這樣的人被稱做戰士,真正的戰士。惋惜是個力量戰士,作爲新時代的智力戰士,固然不能在那跌到而後又在這繼續跌到。
文件的存儲方式:
文件都有本身的存儲格式,好比最多見的txt,cpp,h,c,xml ,png, rmvb各類格式,還有自定義格式。這些文件不管是什麼格式,都是存儲在計算機硬盤裏的2進制格存儲,對應不一樣文件格式,有不一樣的軟件解析。這篇文章不談文件是如何存儲的,只談文件是如何解析的。
文本文件解析:
文本文件對應於人類能夠閱讀的文本,如何從2進制轉換爲文本文件呢?起初因爲計算機在美國發明,天然你們考慮的是英語如何表示,英語字母總共26個,加上特殊字符,128個字符,7位既一個byte便可表示出來。這個就是你們所熟知的ascill編碼。對應關係很簡單,一個字符對應一一個byte。
但很快發現,其餘非英語國家的文字遠遠超過ascill碼,這時候你們固然想統一一下,不一樣國家出了本身不一樣的編碼方式,中國的gb2312就是本身作出來的編碼方式,這樣下去每一個國家都有本身的編碼方式,來回轉換太麻煩了。這時候出現了新的編碼方式,unicode編碼方式,想將編碼統一,因此規定了每一個字符對應的unicode碼。
一、不少文件都是ascii編碼,若是用unicode 太浪費。
二、沒有標誌位說明該幾個字節來解析爲一個符號。
這時候拯救世界的utf出現了,utf是unicode的一種實現,只不過更聰明瞭。utf16是佔用兩字節,或者四字節,utf32是佔用四字節。utf8是很聰明的一種表示方式。
一、對於單字節符號,字節第一位爲0,後面7位表示字節編碼。
二、對於n字節符號,第一字節的前n位都設爲1,第n+1位爲0,其他位位編碼位置。
對於不一樣的編碼,在文本的最前方有不一樣的標誌,unicode 一般有兩位來表示分別是ff fe, 或者feff, fffe表示litte-endian 編碼feff表示big-endian編碼。utf8是efbbbf來開頭的。能夠看出來utf-8是自解釋的,因此不用帶這個標誌文件,大多數程序是能夠識別的。但有些程序不能識別這個標誌,好比php就會直接把這個標誌當文本解析,不會忽略。相信不少遇到php輸出文本解析亂碼或者解析錯誤的同窗都遇到這樣的問題。
最後說說如何去掉或者加上bom,若是有vim那最好不過了,去掉命令:
set encoding=utf-8
set nobomb
添加命令:
set encoding=utf-8
set bomb
---------------------------------------------------------------------------------------------------------------------------
ANSI 確實是遺留編碼,在不一樣語言的系統中編碼不一樣,這一部分在微軟的術語中叫 code page。好比所謂 GBK 編碼,實際上更多地被叫作 CP936。這個術語是從 IBM 早期的一些工做中繼承下來的,如今也沒改變。可是,代碼頁這個概念在引入更大的字符集時已經遇到了問題,好比當初 GBK 擴展到 GB18030 時,它沒法天然地用同一個代碼頁解決問題,不得不使用很是複雜的映射技術在幾個代碼頁中切換才最終達到目的。
所謂微軟的 Unicode,確實是 UTF-16LE。這個問題上 MSDN 文檔在術語運用上有不少先後矛盾的地方,因此不少程序員都不太瞭解。再加上微軟 SDK 默認的 WCHAR 是兩個字節,進一步加重了混亂程度。事實上時至今日,微軟的默認編碼不必定是兩字節了,由於 Unicode 早已超過了 65536 個字符。
若是是爲了跨平臺,那麼最有效的辦法確實是堅持使用 UTF-8。不過是否使用 BOM 則未必真的須要很糾結。事實上現代的編輯器均可以很好地處理 BOM,好比 VIM。在 UNIX 環境下不適合使用 BOM 的場合有兩個:一個是 XML,另外一個是老舊的 shell 腳本。前者是由於規範裏就沒有 BOM 的位置,然後者則是由於歷史緣由而不能很好支持。而更大範圍內的應用,好比 Python 腳本,則能夠很好地處理 BOM。
做者:時國懷
連接:https://www.zhihu.com/question/20650946/answer/15751688
來源:知乎
著做權歸做者全部,轉載請聯繫做者得到受權。
ANSI:最先的時候計算機ASCII碼只能表示256個符號(含控制符號),這個字符集表示英文字母足夠,其中,咱們鍵盤上可見的符號的編碼範圍是從32到126(大小寫英文字母、數字、英文符號等)。但表示漢字、日語、韓語就不太夠用了,漢字經常使用字有3000多個。
可是中國人也要用電腦打字,因而,中國人就研究出來了最先的中文字符集GB2312(GBK就是後來的擴展),GB2312的作法是,把ASC碼取值範圍的128~255這個區間挪用了一下,用兩個ASC碼錶示一個漢字,這樣可用的編碼範圍用十六進制表示就是0x8080到0xFFFF,這大概能表示一萬多個符號,足夠了。[注:實際沒用那麼多,GBK的範圍是8140-FEFE]
那個時候,計算機技術還不發達,各個國家搞本身的,好比臺灣,也另搞了一套,叫BIG5(俗稱:大五碼),跟大陸的也不太同樣,但方法是相似的,都是用0x80到0xFF這個區間。
而後日語(有編碼JIS)、韓語等等也各搞一套。
這些國家的編碼區間都是重疊的,但同一個漢字(好比有一些漢字同時存在於簡體、繁體、日語漢字中)有不一樣的編碼,很混亂是否是?但也湊合用了。編碼不一樣致使了不少麻煩,好比一個網頁,若是你不知道它是什麼編碼的,那麼你可能很難肯定它顯示的是什麼,一個字符多是大陸簡體/臺灣繁體/日本漢字,但又徹底是不一樣的幾個字。
因此若是用一些很老的軟件,可能會據說有中文版/日文版之類的,對應的版本只能在對應的系統上運行。
後來,這個對操做系統的開發實在是太困難了,由於這意味着不一樣語言的版本,都要從新編碼。因而發明了Unicode。
Unicode這個東西,就是要把地球上全部的語言的符號,都用
統一的字符集來表示,一個編碼真正作到了惟一。
Unicode裏有幾種方式:
UTF-16BE/LE:UTF-16就是Windows模式的編碼模式(Windows裏說的Unicode通常都是指這種編碼),用2個字節表示任意字符,注意:英文字符也佔2個字節(變態不?),這種編碼能夠表示65536個字符,至於LE和BE,就是一個數值在內存/磁盤上的保存方式,好比一個編碼0x8182,在磁盤上應該是0x81 0x82呢?仍是0x82 0x81呢?就是高位是最早保存仍是最後保存的問題,前者爲BE,後者爲LE。
UTF-8:UTF-8則是網頁比較流行的一種格式:用一個字節表示英文字符,用3個字節表示漢字,準確的說,UTF-8是用二進制編碼的前綴,若是某個UTF-8的編碼的第一個字節的最高二進制位是0,則這個編碼佔1字節,若是是110,則佔2字節,若是是1110,則佔3字節……
好了,說了這麼,再來研究Windows的記事本。
Windows早期(至少是95年之前的事情了)是ANSI字符集的,也就是說一箇中文文本,在Windows簡體中文版顯示的是中文,到Windows日文版顯示的就不知道是什麼東西了。
後來,Windows支持了Unicode,但當時大部分軟件都是用ANSI編碼的,unicode還不流行,怎麼辦?Windows想了個辦法,就是容許一個默認語言編碼,就是當遇到一個字符串,不是unicode的時候,就用默認語言編碼解釋。(在區域和語言選項裏能夠改默認語言)
這個默認語言,在不一樣Windows語言版本里是不一樣的,在簡體中文版裏,是GBK,在繁體中文版裏,是BIG5,在日文版裏是JIS
而記事本的ANSI編碼,就是這種默認編碼,因此,一箇中文文本,用ANSI編碼保存,在中文版裏編碼是GBK模式保存的時候,到繁體中文版裏,用BIG5讀取,就全亂套了。
記事本也不甘心這樣,因此它要支持Unicode,可是有一個問題,一段二進制編碼,如何肯定它是GBK仍是BIG5仍是UTF-16/UTF-8?記事本的作法是在TXT文件的最前面保存一個標籤,若是記事本打開一個TXT,發現這個標籤,就說明是unicode。標籤叫BOM,若是是0xFF 0xFE,是UTF16LE,若是是0xFE 0xFF則UTF16BE,若是是0xEF 0xBB 0xBF,則是UTF-8。若是沒有這三個東西,那麼就是ANSI,使用操做系統的默認語言編碼來解釋。
Unicode的好處就是,不論你的TXT放到什麼語言版本的Windows上,都能正常顯示。而ANSI編碼則不能。(UTF-8的好處是在網絡環境下,比較節約流量,畢竟網絡裏英文的數據仍是最多的)
舉例:
一樣一段中文文本(能夠插入一些英文),保存成ANSI/Unicode/UTF-8,三個文件。
修改windows的默認語言爲日語之類的(WIN7的改法是:控制面板-時鐘、語言和區域-更改顯示語言-區域和語言-管理-非unicode程序語言-更改區域設置/WNIXP改法是:控制面板-區域和語言選項-非unicode程序語言)。
修改完要求重啓,重啓之後,再打開這三個文件,ANSI的編碼全亂了,其他兩個都正常顯示,這就是UNICODE的做用。
另外,爲何記事本、開始菜單什麼的仍是正確的中文呢?明明我已經改了默認語言了?由於它們的程序編碼也是unicode的。
要把txt發給國外的朋友或者用在非中文的操做系統/軟件裏,那麼你的編碼最好選擇unicode
ASCII是古老的編碼,那個時候還不區分字符集和編碼,基本能夠看做合二爲一的東西。
Unicode嚴格來講是字符集,能夠有多種編碼。
UTF-8是一種Unicode的編碼。
兼容性最好的,我記得好像是UTF-8不帶BOM頭。
注: 字符集(char set)就是字符的集合,收錄了必定數量的字符。每一個字符有對應的ID值,叫碼點(code point)。實際存儲的時候,不必定是直接存儲字符串的碼點(好比,爲了節約空間),要進行轉換。這個轉換規則就是編碼。
發佈過編碼規範的組織有 GB、微軟、Unicode 聯盟和 ISO 等,互相之間有的兼容,有的不兼容。
GB 是國標,中國的一個發佈編碼規範的機構,能夠忽略掉,通用性太差了。
微軟在 GB2312 的基礎上擴展了 GBK,也能夠忽略掉。
UTF-8(一種
編碼方式) 是 Unicode(一種標準) 的實現方式。記事本把 Unicode 和 UTF-8 並列,我不太懂它什麼意思。
ANSI 並非肯定的一種編碼,在簡體中文操做系統指的是 GB2312,在繁體操做系統指的是 BIG5。
一句話,最好用 UTF-8。
多說一句:不要使用 Windows 自帶的記事本!說記事本是垃圾,一點不爲過。
基本的問題是:非英語字符須要擴展 只面向英文的ASCii編碼。
ANSI:泛指最先每種國家語言各自實現的編碼方式,各個編碼互相之間不兼容,比較省空間。
Unicode:一套抽象的兼容全部經常使用語言的編碼方式,可是不適合計算機系統直接存儲。
UTF-8:一種將unicode轉換成適合計算機存儲的方式,
相對其餘的UTF-xx省空間,同時又能夠和ASCII混用,結構相對複雜,底層處理相對慢。
UTF-16,UTF-32:另外的unicode存儲編碼,結構簡單,不能和ASCII混用。
BOM:一種爲了跨平臺設計的文件起始標記,但不少程序沒去處理這個,用了BOM反而常形成問題。
做者:藍色鼓點
連接:https://www.zhihu.com/question/20650946/answer/15755457
來源:知乎
著做權歸做者全部,轉載請聯繫做者得到受權。
1.ANSI 就是ASCII編碼。一個英文字符佔一個字符 2.GB2312 是國內利用ASCII控制字符(即碼值超過127)的兩個字符造成一個漢字的原理。在DOS時代和windows 3.1時代用的就是這個方案,必需要外掛系統來解決顯示問題。 同時代臺灣搞一個BIG5編碼也是相同原理,可是碼值有衝突,因此那個時代txt 亂碼是很頭痛問題。 一個漢字至關於兩個字符。可是這個格式用得仍是不少。網上txt 中文小說幾乎都是這個格式,還有歌詞文件 lrc也是這個格式。後來爲兼容繁體字,後推出一個GBK 大字集。 3. 國標組織爲了解決世界各國的寬字符編碼不統一的問題,搞出一UNICODE編碼。把世界經常使用的語言的字符編一編碼採用兩個字符。世界約有幾萬字符(主要中文吃了一片),所以不一樣國家用不一樣代碼區(code page 區別)(不管英文,漢字,泰文等)均是如此。 windows是內核採用了UNICODE編碼。 可是在應用程序這一級爲了兼容老的程序還有一套API,留給原來的應用程序來用。 4.到了Linux 和Mac OS X, 內核的編碼採用是UTF-8,寬字符如漢字,採用的UTF-8編碼。這個主要是針對網絡傳輸的,從名字就能夠看出來,UCS Transfer For .這個編碼的特色除了統一編碼外,還有的碼值是變長,即一個字符能夠由1-4字符表示,英文就與ASCII對應,漢字最短是兩個字符,最長是四個字符,這個能夠把傳輸字符量減到最小。 UTF8 與UNICODE沒有規律的轉換關係,二者編碼是有衝突的。 -------------------------------------------- 跨平臺開發者要碰到一些問題: 在windows寫的漢字,好比在程序中漢字註釋(不管是UNICODE,仍是GB2312)在LINUX下UTF8顯示均是亂碼。反過來也是同樣。 固然有一些windows工具如UltraEdit 能直接識別,那是應用程序本身做了轉換。 至於說哪一種格式通用,沒有定例,徹底看應用程序的要求。我舉幾個常見例子。 1. 歌詞文件 lrc,從我看的研究來看,哪一個平臺都是採用ANSI + GBK編碼的。你隨便從QQ音樂下載幾個歌詞就知道了。如今從網上下的小說txt ,基因而GBK格式的。 2.java內碼指定是UNICODE編碼,因此你在哪個平臺的Eclipse裏輸入的漢字均採用UNICODE編碼,這樣在Mac OS X 你能夠發如今Eclipse寫的漢字,用XCode 打開就亂碼。 3. XML這一些格式,裏面要求是UTF-8,你能夠看第一句就註明是UTF-8格式。