上周同事組內(nèi)分享了編碼相關(guān)的內(nèi)容。之前自己也總結(jié)過(guò),但過(guò)了一段時(shí)間后發(fā)現(xiàn)記憶有點(diǎn)模糊。希望能從一個(gè)角度講好編碼這件事,理解型記憶。
編碼的理解
在計(jì)算機(jī)的世界中,只有0和1。0和1組成的2進(jìn)制能唯一對(duì)應(yīng)一個(gè)數(shù)字。因此我們所見的所有文字,所有符號(hào),要想在計(jì)算機(jī)中表現(xiàn),只能先對(duì)應(yīng)到一個(gè)數(shù)字上。比如0表示a,1表示b。你以為人類的文字很多,其實(shí)不然,漢字也就幾萬(wàn)的規(guī)模而已。將所有人類日常用到的符號(hào),全部給一個(gè)數(shù)字編號(hào),然后將數(shù)字轉(zhuǎn)換成計(jì)算機(jī)的01,編碼的過(guò)程也就完成了。
任何一個(gè)編碼系統(tǒng)都是如此,也只能如此。這個(gè)過(guò)程中唯一能產(chǎn)生的區(qū)別就是符合對(duì)應(yīng)的數(shù)字可能不同。比如我0表示A, 你的0表示a。另外也可能我只表示英文字符,別的字符不包含,比如ascii碼,而有些包含漢字,不包含拉丁文。這些都是細(xì)枝末節(jié)的區(qū)別。
來(lái)對(duì)漢字進(jìn)行編碼
如果要對(duì)漢字進(jìn)行編碼,首先是獲取到想要編碼的所有漢字,比如6萬(wàn)個(gè)。從0到6萬(wàn)給個(gè)編號(hào),這6萬(wàn)個(gè)漢字就已經(jīng)編碼好了。
剩下的問(wèn)題不過(guò)是如何在計(jì)算機(jī)中進(jìn)行保存。畢竟編號(hào)最小的只需要占用1bit的空間,而編號(hào)最大的可能需要16bit空間(2^16=65536)。
不同編碼的區(qū)別
除了最開始說(shuō)的最細(xì)枝末節(jié)的區(qū)別,不同編碼之間最大的區(qū)別在于,如果在計(jì)算機(jī)中表示相應(yīng)的數(shù)值。
比如上面提到的,要表示從0到6萬(wàn)之間的所有數(shù),如何在計(jì)算機(jī)中表示。最簡(jiǎn)單的是,每個(gè)數(shù)分配16bit的空間也就是2個(gè)字節(jié)來(lái)表示。沒(méi)有一點(diǎn)問(wèn)題。
但對(duì)于1個(gè)字節(jié)就能表示的數(shù),另外一個(gè)字節(jié)就全是0,浪費(fèi)掉了。特別是要表示英文文獻(xiàn)時(shí),大部分都是ascii碼,一個(gè)字節(jié)就能搞定的事情,空間相當(dāng)于浪費(fèi)了一半。
上面用兩個(gè)字節(jié)來(lái)表示成為固定長(zhǎng)度表示。與之相對(duì)的就是變長(zhǎng)表示法。對(duì)于一個(gè)字節(jié)能表示完的,我就用一個(gè)字節(jié),萬(wàn)不得已的時(shí)候,我用更多的直接來(lái)表示。
unicode 編碼
Unicode編碼是一套規(guī)范,規(guī)定的是數(shù)字和符號(hào)之間的對(duì)應(yīng)關(guān)系。
里面具體的編碼規(guī)則如utf-16, utf-8是遵循這套規(guī)范的,且明確在計(jì)算機(jī)中保存這些數(shù)字的格式。
其中utf-16 是固定使用兩個(gè)字節(jié)的長(zhǎng)度來(lái)表示。因此與ascii碼不兼容(當(dāng)需要表示的字符只是ASCII碼時(shí),是否與ASCII 編碼后的二進(jìn)制一樣)--使用utf-16表示abc之后,其二進(jìn)制使用ASCII規(guī)范解碼后為0a0b0c。
固定字節(jié)長(zhǎng)度的編碼都很好實(shí)現(xiàn),解碼工作也非常容易做。但問(wèn)題有兩個(gè)
- 空間浪費(fèi)的問(wèn)題。
- 解碼時(shí)不安全的問(wèn)題。如果因?yàn)槟承┰?,遺漏了一個(gè)字節(jié),則后面所有的解碼都將錯(cuò)誤。
utf-8是使用最多4字節(jié)的變長(zhǎng)編碼。
- 與ASCII兼容。ASCII編碼是一個(gè)字節(jié),且首尾為0。因此當(dāng)解碼時(shí),發(fā)現(xiàn)一個(gè)字節(jié)首位為0,當(dāng)成一個(gè)字節(jié)解讀。
- 在此基礎(chǔ)上,如果首位為1, 則表明這次編碼一定不是一個(gè)字節(jié)??赡苁?,3,4個(gè)字節(jié)三種情況。