1.什麼是字元
字元是書寫的最基本構建單元。字元可以表示字母、數字、標點、表意符號(比如漢字)、數學符號,或者其他的書寫基本單元。
不能把字元和字形相混淆。字元是唯一的,抽象的語言「原子」。字形是畫出每個符號時使用的特定方式。只有當用一種字形替代另一種字形,文字的意思發生了改變,才把這些字形看成是不同的字元。否則,這些字形就是同乙個字元的不同風格的表示形式。
比如上圖中的九個字形,雖然形狀各異,但一看就知道是小寫字母a,所以這九個字形代表的是小寫字母a這同乙個字元。
2.編碼後的字符集(coded character set)
編碼後的字符集將整數對映到字元。編碼後的字符集經常用陣列來實現,通過**數值來進行索引。陣列的元素就是字元。下面舉例說明一些常見的編碼後字符集。
1)us-ascii
ascii表示「美國標準資訊交換**」(american standard code for information interchange)。ascii是最著名的編碼後字符集,早在2023年就由ansi進行了標準化。ascii的**值範圍是0到127(用十六進製制表示是0x00到0x7f),因此只需7個二進位製碼就可以覆蓋整個**空間。ascii的推薦名稱是us-ascii,這樣可以和那些7位字符集的一些國際化變體進行區分。http報文(首部、uri等)使用的字符集是us-ascii。
iso-8859字符集標準是us-ascii的8位超集,使用二進位製碼的高位增加了一些國際化書面字元。有額外的二進位製碼增加的空間(多了128個**,從0x80到0xff)還不夠大,甚至還不夠所有的歐洲字元使用,更不用說亞洲字元了。因此iso-8859為不同地區定製了不同的字符集。其中最著名的就是iso-8859-1,用於表示西歐語言(英語、法語等)。iso-8859-1的別名是latin1,是html的預設字符集。
3)ucs
ucs(universal character set)把全世界的所有字元都整合到了單一的編碼後字符集中。ucs由iso 10646定義。unicode是遵循ucs標準的商業化聯合組織。
在ucs標準中,**空間被分成了17個平面(planes),每個平面有65536(2的16次方)個**點(code points),所以總共有1,114,112個**點。這個數字很奇怪,因為它不是2的冪。這其實是utf-16編碼方案的設計所造成的結果。
在utf-16中,用兩個**單元(共四個位元組)組成的「**對」(surrogate pair)來編碼1到16平面中的2^20個**點(2^4個平面乘以每個平面2^16個**點),而對0平面進行編碼只需要乙個**單元(兩個位元組)。2^20 + 2^16 = 1024^2 + 65536 = 1114112。
ucs中的第乙個平面,0平面,也叫「基本多語種平面」(basic multilingual plane,bmp)。這個平面是到目前為止大部分字元所在的地方。而bmp中的大部分**點都被用於對中日韓的字元進行編碼。上圖中淺灰色區域中,0xd800到0xdfff(8 * 2^8 = 2^11 = 2048)這個區域(倒數第三行後半部分)不對應任何字元,而是被保留用於在utf-16編碼方案中對**對進行編碼。
3.字元編碼方案(character encoding scheme)
字元編碼方案(character encoding scheme)和編碼後的字符集(coded character set)不是乙個概念。字符集給所包含的每個字元分配乙個整數編號,而編碼方案規定如何把字元的**數字打包裝入二進位制的位元資料中,以及如何在另一端將其解包回字元**。
字元編碼方案主要有以下3種型別。
ÿ固定寬度
固定寬度方式的編碼用固定數量的位元表示每個編碼後的字元。它們能被快速處理,但可能會浪費空間。
ÿ可變寬度
可變寬度方式的編碼對不同的字元**數字採用不同數量的位元。對於常用字元,這樣可以減少所需的位數,而且還能在允許使用多位元組來表示國際性字元的同時,保持對傳統8位字符集的相容性。
可變寬度(有模態)
有模態的編碼使用特殊的「轉義」模式在不同的模態之間進行切換。例如,可以用有模態的編碼在文字中使用多個互相重疊的字符集。有模態的編碼處理起來比較複雜,但可以有效地支援複雜的書寫系統。
1)8位編碼
iso-8859字符集家族系列使用的是8位的恒等編碼。這種編碼把每個字元**直接編碼為相應的8位二進位制數值。這種編碼方式只支援**範圍包含256個字元的字符集。
2)utf-8
utf-8是一種流行的為ucs設計的字元編碼方案,utf表示ucs變換格式(ucs transformation format)。utf-8為字元**值使用的是無模態的變寬編碼。第乙個位元組的高位表示編碼後字元所用的位元組數,後續每個位元組都固定包含6位的**值。
如果編碼後的第乙個位元組的最高位是0,則編碼長度就是乙個位元組,剩餘的7位就包含字元的**。這樣一來就美妙地達到了與ascii的相容(但和iso-8856系列不相容)。
例如字元**90(ascii的「z」)在0到127的範圍內,故只需乙個位元組進行編碼(90 = 64 + 16 + 8 + 2 = 2^6 + 2^4 + 2^3 + 2,編碼為0,101,1010)。而**5073需要13位二進位制數(1,001111,010001),會被編碼為3個位元組(見上圖第三行):
11100001100011111001001
注意utf-8的最大編碼值是31位,能編碼2^31個**值,這遠遠大於ucs的**範圍(相當於2^15,即32768個平面)。
3)utf-16
utf-16編碼方案能夠對ucs中的1,112,064個**點進行編碼(1,114,112減去從u+d800到u+dfff這2048個用於**對的**點)。utf-16編碼長度要麼是兩個位元組(對於從u+0000到u+d7ff,以及從u+e000到u+ffff的基本平面**點),要麼是4個位元組(對於從u+1,0000到u+10,ffff的16個輔助平面中的**點)。
輔助平面中的**點長度超過兩個位元組,用兩個16位的**單元(稱為乙個**對)來進行編碼,具體編碼方式如下:
從這裡就能看出為什麼要保留0xd800到0xdfff這個範圍了,因為0xdfff – 0xd800 + 1等於0x800,等於2 * 2^10,即切成兩半,每一半可以**表示2^10個數,組合起來正好可以**表示2^20個輔助平面中的**點(2^10 * 2^10 = 2^20)。
思考一下為什麼要用**對來進行編碼,而不是用4個位元組直接表示輔助平面中**點的值?
字元編碼相關總結
1 一位元組byte 8位元bit,so,一位元組能表示的最大的整數就是255 二進位制 1111 1111 2 最早ascii編碼,用乙個位元組byte來表示127個字元,包括 大小寫英文本母,數字,一些符號 3 中國gb2312編碼 加入中文的編碼。與此同時,各國有對應編碼。多國語言就會導致亂碼...
字元編碼相關總結
場景1 在html中定義表單submit form,通過js中的 submit form ajaxsubmit提交表單,但是在後端收到表單提交的中文顯示亂碼。前段部分 如下 test.html form id insterfestivals form method post br p label f...
字元編碼 知識總結
工作中經常遇到中文亂碼的問題,由於歷史的原因,工作中經常遇到檔案編碼不一致的情況。老員工之前使用的是gbk編碼,新來的拿到之前的 用utf8編碼開啟,就會出現亂碼,我就經常遇到這樣的情況。不同系統間傳遞檔案也會出現亂碼的情況,比如蘋果系統開啟windows系統的檔案,也會有亂碼。今天來學習一下計算機...