上周同事組內(nèi)分享了編碼相關(guān)的內(nèi)容。之前自己也總結(jié)過堂飞,但過了一段時(shí)間后發(fā)現(xiàn)記憶有點(diǎn)模糊。希望能從一個(gè)角度講好編碼這件事绑咱,理解型記憶绰筛。
編碼的理解
在計(jì)算機(jī)的世界中,只有0和1描融。0和1組成的2進(jìn)制能唯一對應(yīng)一個(gè)數(shù)字铝噩。因此我們所見的所有文字,所有符號窿克,要想在計(jì)算機(jī)中表現(xiàn)骏庸,只能先對應(yīng)到一個(gè)數(shù)字上。比如0表示a年叮,1表示b具被。你以為人類的文字很多,其實(shí)不然只损,漢字也就幾萬的規(guī)模而已硬猫。將所有人類日常用到的符號,全部給一個(gè)數(shù)字編號,然后將數(shù)字轉(zhuǎn)換成計(jì)算機(jī)的01啸蜜,編碼的過程也就完成了坑雅。
任何一個(gè)編碼系統(tǒng)都是如此,也只能如此衬横。這個(gè)過程中唯一能產(chǎn)生的區(qū)別就是符合對應(yīng)的數(shù)字可能不同裹粤。比如我0表示A, 你的0表示a蜂林。另外也可能我只表示英文字符遥诉,別的字符不包含,比如ascii碼噪叙,而有些包含漢字矮锈,不包含拉丁文。這些都是細(xì)枝末節(jié)的區(qū)別睁蕾。
來對漢字進(jìn)行編碼
如果要對漢字進(jìn)行編碼苞笨,首先是獲取到想要編碼的所有漢字,比如6萬個(gè)子眶。從0到6萬給個(gè)編號瀑凝,這6萬個(gè)漢字就已經(jīng)編碼好了。
剩下的問題不過是如何在計(jì)算機(jī)中進(jìn)行保存臭杰。畢竟編號最小的只需要占用1bit的空間粤咪,而編號最大的可能需要16bit空間(2^16=65536)。
不同編碼的區(qū)別
除了最開始說的最細(xì)枝末節(jié)的區(qū)別渴杆,不同編碼之間最大的區(qū)別在于寥枝,如果在計(jì)算機(jī)中表示相應(yīng)的數(shù)值。
比如上面提到的磁奖,要表示從0到6萬之間的所有數(shù)囊拜,如何在計(jì)算機(jī)中表示。最簡單的是点寥,每個(gè)數(shù)分配16bit的空間也就是2個(gè)字節(jié)來表示艾疟。沒有一點(diǎn)問題来吩。
但對于1個(gè)字節(jié)就能表示的數(shù)敢辩,另外一個(gè)字節(jié)就全是0,浪費(fèi)掉了弟疆。特別是要表示英文文獻(xiàn)時(shí)戚长,大部分都是ascii碼,一個(gè)字節(jié)就能搞定的事情怠苔,空間相當(dāng)于浪費(fèi)了一半同廉。
上面用兩個(gè)字節(jié)來表示成為固定長度表示。與之相對的就是變長表示法。對于一個(gè)字節(jié)能表示完的迫肖,我就用一個(gè)字節(jié)锅劝,萬不得已的時(shí)候,我用更多的直接來表示蟆湖。
unicode 編碼
Unicode編碼是一套規(guī)范故爵,規(guī)定的是數(shù)字和符號之間的對應(yīng)關(guān)系。
里面具體的編碼規(guī)則如utf-16, utf-8是遵循這套規(guī)范的隅津,且明確在計(jì)算機(jī)中保存這些數(shù)字的格式诬垂。
其中utf-16 是固定使用兩個(gè)字節(jié)的長度來表示。因此與ascii碼不兼容(當(dāng)需要表示的字符只是ASCII碼時(shí)伦仍,是否與ASCII 編碼后的二進(jìn)制一樣)--使用utf-16表示abc之后结窘,其二進(jìn)制使用ASCII規(guī)范解碼后為0a0b0c。
固定字節(jié)長度的編碼都很好實(shí)現(xiàn)充蓝,解碼工作也非常容易做隧枫。但問題有兩個(gè)
- 空間浪費(fèi)的問題。
- 解碼時(shí)不安全的問題棺克。如果因?yàn)槟承┰蛴贫猓z漏了一個(gè)字節(jié),則后面所有的解碼都將錯(cuò)誤娜谊。
utf-8是使用最多4字節(jié)的變長編碼确买。
- 與ASCII兼容。ASCII編碼是一個(gè)字節(jié)纱皆,且首尾為0湾趾。因此當(dāng)解碼時(shí),發(fā)現(xiàn)一個(gè)字節(jié)首位為0派草,當(dāng)成一個(gè)字節(jié)解讀搀缠。
- 在此基礎(chǔ)上,如果首位為1近迁, 則表明這次編碼一定不是一個(gè)字節(jié)艺普。可能是2鉴竭,3歧譬,4個(gè)字節(jié)三種情況。