3. unicode 字符集& utf-8 編碼
4. 總結
參考(**個人部落格)
想要弄明白文字的編碼是怎麼回事,繞不過去字符集和字元編碼這兩個概念。
我們知道,位元組是計算機中對二進位制序列表達最常用的單位,一位元組的長度是8位,能夠表達256種不同的狀態,也就是256個不同的字元。
每一種技術的出現,伴隨其制定的標準在最初都無法囊括未來出現的所有情況。字元編碼就是如此。
最開始,美國發明了計算機。與之相伴的,美國規定了能夠表達包括英文本母大小寫在內的128個字元(也包括了一些控制符,比如響鈴、退格等等),我們可以把這128個字元集合稱作 ascii 字符集。伴隨著的是對應在計算機中的二進位制位元組編碼,也就可以稱作 ascii 編碼。
為了表示更多的歐洲等國家使用的字元,對原始的 ascii 編碼範圍進行了擴充,採用乙個位元組 256 種不同狀態來表示 256 種不同的字元。
iso-8859-1編碼是單位元組編碼,向下相容ascii,其編碼範圍是0x00-0xff,0x00-0x7f之間完全和ascii一致,0x80-0x9f之間是控制字元,0xa0-0xff之間是文字元號。
iso-8859-1收錄的字元除ascii收錄的字元外,還包括西歐語言、希臘語、泰語、阿拉伯語、希伯來語對應的文字元號。歐元符號出現的比較晚,沒有被收錄在iso-8859-1當中。
iso-8859-1 的較低部分(從 1 到 127 之間的**)是最初的7位 ascii。iso-8859-1 的較高部分(從 160 到 255 之間的**)全都有實體名稱。
因為iso-8859-1編碼範圍使用了單位元組內的所有空間(即8位,0-255),在支援iso-8859-1的系統中傳輸和儲存其他任何編碼的位元組流都不會被拋棄。換言之,把其他任何編碼的位元組流當作iso-8859-1編碼看待都沒有問題。這是個很重要的特性,mysql資料庫預設編碼是latin1就是利用了這個特性。ascii編碼是乙個7位的容器,iso-8859-1編碼是乙個8位的容器。
latin1是iso-8859-1的別名,有些環境下寫作latin-1。
為了解決漢字在計算機中的編碼問題,最開始推行的方案是採用兩個位元組對常用的 6763 個漢字和其它一些符號進行編碼。同時為了保證對 ascii 編碼的相容性,每個位元組的最高一位位元總是為 1。這樣計算機遇到高位為1的位元組就會採用漢字編碼方案,遇到高位為0的位元組採用 ascii 編碼方案。這種解決方法我們就可以稱為 gb2312 編碼方案。
雖然 gb2312 編碼能夠覆蓋99.75%使用頻率的漢字,畢竟還是有無法編碼的字存在。gbk 的出現彌補了少數漢字無法進行編碼解析的問題,它是 gb2312 編碼的擴充套件,向下相容 gb2312,同時包含了繁體字。
gb18030 進一步擴充套件了 gbk 所包含的字符集範圍,囊括了中國少數民族所用的字元等。同時也是向下相容 gbk、gb2312的。
與 gb2312 等編碼標準的出現相似,big5編碼 主要是台灣地區為了解決對繁體字的處理。shift_jis 為日本電腦系統常用的編碼方案,euc-kr 為南韓電腦系統常用編碼方案。
第2節中提到的各個編碼方案可以統歸為 ansi 編碼。
如上 ansi 編碼條例中所述,世界上存在著多種編碼方式,在 ansi 編碼下,同乙個編碼值,在不同的編碼體系裡代表著不同的字。在簡體中文系統下,ansi 編碼代表 gb2312 編碼,在日文作業系統下,ansi 編碼代表 jis 編碼,可能最終顯示的是中文,也可能顯示的是日文。在 ansi 編碼體系下,要想開啟乙個文字檔案,不但要知道它的編碼方式,還要安裝有對應編碼表,否則就可能無法讀取或出現亂碼。為什麼電子郵件和網頁都經常會出現亂碼,就是因為資訊的提供者可能是日文的 ansi 編碼體系而資訊的讀取者可能是中文的編碼體系,他們對同乙個二進位制編碼值進行顯示,採用了不同的編碼,導致亂碼。這個問題促使了 unicode 碼的誕生。
如果有一種編碼,將世界上所有的符號都納入其中,無論是英文、日文、還是中文等,大家都使用這個編碼表,就不會出現編碼不匹配現象。每個符號對應乙個唯一的編碼,亂碼問題就不存在了。這就是 unicode 編碼。
unicode 現在的規模可以容納100多萬個符號。每個符號的編碼都不一樣,比如,u+0639表示阿拉伯字母ain,u+0041表示英語的大寫字母a,「漢」這個字的unicode編碼是u+6c49。
需要注意的是,unicode只是乙個字符集,它只規定了符號與二進位制**之間的對應關係,卻沒有規定這個二進位制**應該如何儲存。
比如,漢字"嚴"的unicode是十六進製制數4e25,轉換成二進位制數足足有15位(100111000100101),也就是說這個符號的表示至少需要2個位元組。表示其他更大的符號,可能需要3個位元組或者4個位元組,甚至更多。
這裡就有兩個嚴重的問題,第乙個問題是,如何才能區別 unicode 和 ascii ?計算機怎麼知道三個位元組表示乙個符號,而不是分別表示三個符號呢?第二個問題是,我們已經知道,英文本母只用乙個位元組表示就夠了,如果 unicode 統一規定,每個符號用三個或四個位元組表示,那麼每個英文本母前都必然有二到三個位元組是0,這對於儲存來說是極大的浪費,文字檔案的大小會因此大出二三倍,這是無法接受的。
utf-8 是 unicode 的實現方式之一。
utf-8(ucstransformation format 8bit)就是在網際網路上使用最廣的一種 unicode 的實現方式。其他實現方式還包括 utf-16(字元用兩個位元組或四個位元組表示)和 utf-32(字元用四個位元組表示)等,不過在網際網路上用的很少。
utf-8 最大的乙個特點,就是它是一種變長的編碼方式。它可以使用1~4個位元組表示乙個符號,根據不同的符號而變化位元組長度。
utf-8的編碼規則很簡單,只有二條:
對於單位元組的符號,位元組的第一位設為0,後面7位為這個符號的 unicode 碼。因此對於英語字母,utf-8 編碼和 ascii 碼是相同的。
對於n位元組的符號(n>1),第乙個位元組的前n位都設為1,第n+1位設為0,後面位元組的前兩位一律設為10。剩下的沒有提及的二進位制位,全部為這個符號的 unicode 碼。
下表總結了編碼規則,字母x表示可用編碼的位。
unicode 符號範圍(十六進製制)
utf-8 編碼方式(二進位制)
0000 0000-0000 007f
0******x
0000 0080-0000 07ff
110***xx 10******
0000 0800-0000 ffff
1110***x 10****** 10******
0001 0000-0010 ffff
11110*** 10****** 10****** 10******
跟據上表,解讀 utf-8 編碼非常簡單。如果乙個位元組的第一位是0,則這個位元組單獨就是乙個字元;如果第一位是1,則連續有多少個1,就表示當前字元占用多少個位元組。
下面以漢字"嚴"為例,演示如何實現 utf-8 編碼。
已知"嚴"的 unicode 是 4e25(100111000100101),根據上表,可以發現 4e25 處在第三行的範圍內(0000 0800-0000 ffff),因此"嚴"的 utf-8 編碼需要三個位元組,即格式是"1110***x 10****** 10******"。然後,從"嚴"的最後乙個二進位制位開始,依次從後向前填入格式中的x,多出的位補0。這樣就得到了,「嚴"的utf-8編碼是"11100100 10111000 10100101」,轉換成十六進製制就是e4b8a5。
經過上邊的介紹,我們可以大致認為,現在流行的一些編碼方案都是在相容 ascii 的基礎上來實現的。為了滿足各國家地區的更多字元的編碼需求,出現了 ansi 編碼標準,但是該編碼標準在具體各地區國家的實現上是彼此不相容的。為了滿足世界各國字元編碼的相容性需求,unicode 定義了乙個統
一、完備的字符集。為了實現 unicode 字符集在編碼上的需求,又誕生了 utf-8、utf-16等等編碼方案。
最後用一張圖來說明。
字元編碼筆記:ascii,unicode和utf-8
字符集詳解(一看就懂系列)
字元編碼(ascii、ansi、gb2312、utf-8等)系統梳理
字符集和字元編碼(charset & encoding)
十分鐘搞清字符集和字元編碼
ansi是什麼編碼?
搞懂ascii, iso8859-1, ansi和unicode
basic multilingual plane (bmp)
unicode 字符集與它的編碼方式
字符集和字元編碼學習
做嵌入式應用軟體開發,總是少不了要跟字符集和字元編碼打交道。字符集是各種文字和符號的總稱。常見的字符集有ascii字符集 gb2312字符集 big5字符集 unicode字符集等,每一種字符集支援的字元個數並不相同。因為計算機無法像人類一樣識別自然界中的具體事物,它只能識別0和1這兩個二進位制數字...
字符集 字元編碼總結
字符集 charset 是乙個系統支援的所有抽象字元的集合。字元是各種文字和符號的總稱,包括各國家文字 標點符號 圖形符號 數字等。字元編碼 是一套規則,將字元和二進位制資料建立對映關係。1 ascll american standard code for information interchan...
Ruby 字符集和編碼學習總結
ruby直到1.9版本才很好的支援了多位元組編碼,本文簡單總結了今天學習的關於ruby編碼方面的知識。在.net中字串的編碼是一致的,ruby允許字串有不同的編碼,當時我就在想 如果兩個不同編碼的字串相加會出現什麼結果?測試程式 1 coding utf 8 23 str utf8 hi 段 4 p...