當我們在網路傳輸資訊的時候,底層是按照0/1方式來傳輸,問題來了,當接收方接收到一連串0/1之後,接收方該如何分割0/1字串呢?
ascii一開始1位元組(8位)來傳輸,後來gb2312採取變長方式來編碼,這是因為當遇到漢字時採取2位元組編碼,遇到ascii再用1位元組編碼,說白了gb2312動態變化主要是為了相容1位元組的ascii。
再加上其他國家的國家標準,因此不同長度的編碼方式層出不窮,為了方便計算機在全世界推廣,解決不同國家編碼長度不同的問題,為此發明了unicode字符集。
unicode一開始是按照固定2位元組的方式來推廣,即2^16次方個字元(有些軟體unicode字符集的編碼預設是utf16的原因),後來發現固定2位元組還是不夠,還得繼續擴充。但是在擴容的時候發現乙個問題:雖然位元組越多,其表示的字元量越大,但是這會導致字元在記憶體中佔據較大的容量,進而有點浪費記憶體。
如果採用定長編碼方式的話,那麼該定多長是個問題,另外有些生僻字元被用到的概率很小,即便用也就是用幾次而已,有必要為小概率字元而設定較長的定長編碼方式嗎??????
utf16採用2位元組儲存ascii碼,為了解決浪費問題,發明了utf8來解決這個問題,當然utf8也可以用3位元組或者4位元組來儲存漢字,說實話,在中英文混雜的情況下,utf8的效率比不上gbk、gb2312等。
因此結合上面資訊,unicode最後採用變長的編碼方案。下面重點講解變長的規則:
這裡還是要回到編號上面,由於是乙個二維平面,因此每個編號都會用乙個「碼點」來表示。
碼點是用u+[xx]***x形式來表示,x代表乙個十六制數字,最少為4位,最長為6位,不足4位的前補0補足4位,超過4位則按是幾位就是幾位。
碼點取值範圍時u+0000~u+10ffff,這裡是按照最短4位、最長6位的方式來編寫,因此:
從u+0000到u+ffff一共有65536個碼點,
而從u+ffff到u+10ffff即有10個ffff,由於是16進製制,這裡的10換成十進位制就是17,也就是一共有17個65535。
為了方便管理這17個65535,unicode把每65536個碼點看成乙個平面,這樣就一共有17個平面(plane),平面編號從0開始直到16。
其中第乙個平面即plane0叫做bmp,它的碼點範圍是u+0000到u+ffff,該平面內的字元是我們最常用的平面,日常用到的字元絕大多數都落在這個平面內,因此當utf-16遇到此平面內的字元時只需要用兩位元組來編碼字元。
每個plane都是乙個256×256=65536的**,橫向/縱向都是從 00到ff。
plane1-plane16叫做增補平面(sp),對於這些平面內的字元,utf-16採用了四位元組編碼。
我們說碼點最大的 10ffff 也就 21 位,而
utf-32採用的是定長4位元組,即32位。而unicode最大10ffff 也就21位,所以只要把碼點的表示形式以前補0的形式補夠32位即可。
utf-8是變長的編碼方案,其長度分為:1位元組、2位元組、3位元組、4位元組。
utf-8採用高位保留方式來區別不同變長:
1位元組:0******x
2位元組:110***xx 10******
3位元組:1110***x 10****** 10******
4位元組:11110*** 10****** 10****** 10****** 10******
保留的高位是固定位,固定不變的。x表示是有效編碼位。
1位元組最高位都是0,多位元組的最高位都是1。可以總結為:n位元組模式(n>1),首位元組以n個1再加0來打頭,後跟n-1個以10打頭的位元組。
那碼點具體如何從這4種編碼方式中選擇呢?
先把碼點變成二進位制,然後看它有多少有效位(去掉前導0)來確定編碼方式:
1位元組:因為1位元組有效編碼為就7個,因此碼點有效編碼位有7位的話,就用1位元組來編碼。1位元組主要是留給ascii,所以utf-8相容ascii。碼點 u+0000到u+007f(0~127)
2位元組:2位元組有效編碼位只有11位,只有2^11=2048個編碼空間,所以無法存放漢字。碼點 u+0080到u+07ff(128~2047)使用二位元組。
3位元組:3位元組有效編碼位是16位,因此2^16=65536個,碼點u+0800到u+ffff(2048~65535)使用三位元組編碼。常用的漢字就落在這個區間。
4位元組:4位元組有效位是21 位,前面說到最大的碼點10ffff也是21位,u+ffff以上的增補平面的字元都在這裡來表示。
按照utf-8的模式,它還可以擴充套件到5位元組、6位元組甚至更長,但unicode規定碼點就到10ffff,不擴充了,所以utf-8最多到四位元組就足夠了。
utf-16是一種變長的2或4位元組編碼模式。對於plane0 bmp內的字元使用2位元組編碼,其它的則使用4位元組組成所謂的**對來編碼。
先說說**區:
00...
ff...
d8d9
dadb
dcdd
dedf
上面是plane0即bmp中,縱向從d8到df,這8行是空白行。其中d8到db屬於高**區,而dc到df屬於低**區。
這樣各個**區就有:4 * 256 = 1024個。
這樣的話,高**區有如下編號:
d800-d8ff d900-d9ff da00-daff db00-dbff共1024個。
同樣低**區就有:
dc00-dcff dd00-ddff de00-deff df00-dfff共1024個。
當把乙個d8-db共1024個編號當做豎座標,而dc-df當做橫座標,這個平面二維**就有1024*1024=16*65536個**。
而後面也恰恰有16個增補平面,即:plane1-plane16,正好可以容納後面16個增補平面的字元量。
再說說**對:
乙個高**區(d8-db豎座標)的加乙個低**區(dc-df橫座標)的編碼組成一對即是乙個**對,必須是這種先高後低的順序。
再回到原題,即碼點與utf-16如何轉換?
首先,bmp中直接對應的,無須做任何轉換,直接2位元組儲存。
其次,位於增補平面sp中的,這就需要計算其**對是多少,有點複雜,這裡就不講了。
《如何連線網路》第四章
首先,我們在上一章的傳輸技術夠用了嗎?不夠的,因為如果遠距離傳輸還用雙絞線什麼的,根本沒法正常使用。所以會有遠距離傳輸技術,本章涉及這些。另一點,遠距離傳輸的成本很大的,所以一般有運營商負責,那運營商在網路傳輸中做了什麼,本章也講了這個。為了方便理解,我用我的理解講這一段內容,內容會很模糊,具體的知...
第四章 繼承
一 為什麼要繼承 在物件導向中我們將具有很多重複內容的類中的內容提取出來,寫成乙個單獨的類 其他類只需要繼承就能取得這些功能,同時可以在自己類中寫入獨特的自定義方法 二 繼承語法 inte ce circle nsobject 繼承是在介面中定義的 冒號後的類名是要整合的類,nsobject 是co...
第四章 物件
三個特性 身份 型別 值 每個物件都有唯一的身份來標識自己,使用內建函式id 得到。例子 usr bin env python coding utf 8 a 32 print a b a print id a id b 結果 d python27 python.exe e workp python ...