ASCII码、ISO8859-1、Unicode、GBK和UTF-8 的区别
為什么需要編碼?
計算機中最小的存儲單位是字節(jié)(byte),一個字節(jié)所能表示的字符數(shù)又有限,1byte=8bit,一個字節(jié)最多也只能表示255個字符,而世界上的語種又多,都有各種不同的字符,無法用一個byte表示,所以java中的char表示字符就是來解決這種編碼問題的,一個char占兩個字節(jié),所以從char到最小單位byte之間必須經(jīng)過編碼,反之為解碼。
其實,編碼解碼就是完成的翻譯過程(“翻譯”很容易理解吧),各種編碼方式就是一部部字典。
?
?
1、ASCII碼
全稱為American Standard Code for Information Interchange,美國信息交換標準代碼,這是世界上最通用的單字節(jié)編碼系統(tǒng),主要用來顯示現(xiàn)代英語及其他西歐語言。
ASCII碼用7位表示,只能表示128個字符,0~31表示控制字符如回車、退格、刪除等;32~126表示打印字符即可以通過鍵盤輸入并且能顯示出來的字符,
其中48~57為0到9十個阿拉伯數(shù)字,65~90為26個大寫英文字母,97~122號為26個小寫英文字母,其余為一些標點符號、運算符號等,具體可以參考ASCII標準表。
?
2、ISO-8859-1
該編碼是在ASCII編碼的基礎(chǔ)上擴展出來的,但它仍然是單字節(jié)編碼,總共只能表示256個字符。
既然ASCII只能表示128個字符,顯示是不能完全表示完的,所以ISO-8859-1擴展了ASCII編碼,在ASCII編碼之上又增加了西歐語言、希臘語、泰語、阿拉伯語、希伯來語對應(yīng)的文字符號,它是向下兼容ASCII編碼的。
?
3、GB2312
GB2312的全稱是《信息技術(shù) 中文編碼字符集》,它是雙字節(jié)編碼,編碼范圍是A1-F7,其中A1-A9是符號區(qū),總共包含682個符號;B0-F7是漢字區(qū),包含6763個漢字。
全稱為信息交換用漢字編碼字符集,是中國于1980年發(fā)布,主要用于計算機系統(tǒng)中的漢字處理。GB2312主要收錄了6763個漢字、682個符號。
GB2312覆蓋了漢字的大部分使用率,但不能處理像古漢語等特殊的罕用字,所以后來出現(xiàn)了像GBK、GB18030這種編碼。
?
4、GBK
GBK的全稱是《漢字內(nèi)碼擴展規(guī)范》,它的出現(xiàn)是為了擴展GB2312,它的編碼范圍是8140-FEFE(去掉XX7F),總共有23940個碼位,能表示21003個漢字,它的編碼是和GB2312兼容的
GBK,全稱為Chinese Internal Code Specification,即漢字內(nèi)碼擴展規(guī)范,于1995年制定。它主要是擴展了GB2312,在它的基礎(chǔ)上又加了更多的漢字,它一共收錄了21003個漢字。
GBK是向下兼容GB2312編碼的,也就是說GB2312編碼的漢字可以用GBK正常解碼不會出現(xiàn)亂碼,但用GBK編碼的漢字用GB2312解碼就不一定了。
?
5、GB18030
GB18030全稱漢字內(nèi)碼擴展規(guī)范,是現(xiàn)在最新的內(nèi)碼字集于2000年發(fā)布,并于2001年強制執(zhí)行,包含了中國大部分少數(shù)民族的語言字符,收錄漢字數(shù)超過70000余個。
它主要采用單字節(jié)、雙字節(jié)、四字節(jié)對字符編碼,它是向下兼容GB2312和GBK的,雖然是我國的強制使用標準,但在實際生產(chǎn)中很少用到,用得最多的反而是GBK和GB2312。
?
6.UNICODE
為了自己的語言能在計算機中正常顯示,每個國家和地區(qū)都有各自的編碼,所以編碼多了誰也不認識對方的編碼,這時候ISO組織就提出了一種新的編碼叫UNICODE編碼讓全球的文化、字符、符號都能支持。UNICODE在制定時計算機容量已不是問題,所以設(shè)計成了固定兩個字節(jié),所有的字符都用16位表示,包括之前只占8位的英文字符等,所以會造成空間的浪費,UNICODE在很長的一段時間內(nèi)都沒有得到推廣應(yīng)用。
?
7、UTF-16
UTF-16的出現(xiàn)是ISO想要創(chuàng)建一個全新的超語言字典,世界上所有的語言都可以通過這個字典來相互翻譯,可想而知,這個字典是多么的復(fù)雜、龐大。UTF-16用兩個字節(jié)來表示Unicode的轉(zhuǎn)化格式(兩個字節(jié)就是16個bit,所以要UTF-16),采用的是定長的表示方法,即任何字符都可以用兩個字節(jié)表示。這樣表示字符就是變得的非常方便。但是,也有一個缺陷,就是很大一部分的字符用一個字節(jié)就可以表示了,UTF-16卻用兩個字節(jié),有些浪費存儲空間。所以有另一個編碼方式就出現(xiàn)了,也就是UTF-8。
UTF-16是UNICODE的具體實現(xiàn),16即16位,UTF-16即是這個來由,定義了UNICODE字符在計算機中的存儲方式,UTF-16同樣使用了兩個字節(jié)來表示任何字符,這樣使得操作字符串非常高效,這也是java把UTF-16作為字符在內(nèi)存中存儲的格式的重要原因。
UTF-16適合在磁盤與內(nèi)存之間使用,字符和字節(jié)的相互轉(zhuǎn)換會更加簡單和高效,但不適合在網(wǎng)絡(luò)上傳輸,因為網(wǎng)絡(luò)傳輸可能會損壞字節(jié)流。
?
?
8、UTF-8
UTF-8采用了一種變長技術(shù),每個編碼區(qū)域有不同的字碼長度,不同類型的字符可以由1-6個字節(jié)組成。
UTF-8的編碼規(guī)則如下:
1) 如果是1個字節(jié),最高位為0,則表示這是1個ASCII字符。可見,所有ASCII編碼已經(jīng)是UTF-8了
2) 如果是1個字節(jié),以11開頭,則連續(xù)的1的個數(shù)暗示這個字符的字節(jié)數(shù),例如:110xxxxx代表它是雙字節(jié)UTF-8字符的首字節(jié)
3) 如果是1個字節(jié),以10開始,表示它不是首字節(jié),則需要向前查找才能得到當前字符的首字節(jié)。
?
?雖然UTF-16很高效,但也是UNICODE最大的壞處,使得所有單字節(jié)字符一定要占兩個字節(jié),存儲空間放大了一倍,這明顯消耗了資源,不符合現(xiàn)在互聯(lián)網(wǎng)高速發(fā)展的現(xiàn)狀。所以有了UTF-8,它是UNICODE的一種可變長度字符編碼的實現(xiàn),它可以使用1~6個定長字節(jié)來編碼UNICODE字符。
UTF-8對ASCII字符使用單字節(jié)存儲,單個字符損壞也不會影響后面的字符,所以UTF-8非常適合在網(wǎng)絡(luò)上面?zhèn)鹘y(tǒng),也是現(xiàn)在使用最廣泛的編碼之一。
如果要表示中文,UTF-8編碼效率要大于GBK,小于UTF-16,所以它也是除了GBK之外最理想的編碼方式。
?
?
?
?
?
=======================================================================================
本文主要包括以下幾個方面:編碼基本知識,java,系統(tǒng)軟件,url,工具軟件等。
??? 在下面的描述中,將以"中文"兩個字為例,經(jīng)查表可以知道其GB2312編碼是"d6d0 cec4",Unicode編碼為"4e2d 6587",UTF編碼就是"e4b8ad e69687"。注意,這兩個字沒有iso8859-1編碼,但可以用iso8859-1編碼來"表示"。
2. 編碼基本知識
??? 最早的編碼是iso8859-1,和ascii編碼相似。但為了方便表示各種各樣的語言,逐漸出現(xiàn)了很多標準編碼,重要的有如下幾個。
2.1. iso8859-1
??? 屬于單字節(jié)編碼,最多能表示的字符范圍是0-255,應(yīng)用于英文系列。比如,字母a的編碼為0x61=97。
很明顯,iso8859-1編碼表示的字符范圍很窄,無法表示中文字符。但是,由于是單字節(jié)編碼,和計算機最基礎(chǔ)的表示單位一致,所以很多時候,仍舊使用iso8859-1編碼來表示。而且在很多協(xié)議上,默認使用該編碼。比如,雖然"中文"兩個字不存在iso8859-1編碼,以gb2312編碼為例,應(yīng)該是"d6d0 cec4"兩個字符,使用iso8859-1編碼的時候則將它拆開為4個字節(jié)來表示:"d6 d0 ce c4"(事實上,在進行存儲的時候,也是以字節(jié)為單位處理的)。而如果是UTF編碼,則是6個字節(jié)"e4 b8 ad e6 96 87"。很明顯,這種表示方法還需要以另一種編碼為基礎(chǔ)。
2.2. GB2312/GBK
??? 這就是漢子的國標碼,專門用來表示漢字,是雙字節(jié)編碼,而英文字母和iso8859-1一致(兼容iso8859-1編碼)。其中g(shù)bk編碼能夠用來同時表示繁體字和簡體字,而gb2312只能表示簡體字,gbk是兼容gb2312編碼的。
2.3. unicode
??? 這是最統(tǒng)一的編碼,可以用來表示所有語言的字符,而且是定長雙字節(jié)(也有四字節(jié)的)編碼,包括英文字母在內(nèi)。所以可以說它是不兼容iso8859-1編碼的,也不兼容任何編碼。不過,相對于iso8859-1編碼來說,uniocode編碼只是在前面增加了一個0字節(jié),比如字母a為"00 61"。
需要說明的是,定長編碼便于計算機處理(注意GB2312/GBK不是定長編碼),而unicode又可以用來表示所有字符,所以在很多軟件內(nèi)部是使用unicode編碼來處理的,比如java。
2.4. UTF
??? 考慮到unicode編碼不兼容iso8859-1編碼,而且容易占用更多的空間:因為對于英文字母,unicode也需要兩個字節(jié)來表示。所以unicode不便于傳輸和存儲。因此而產(chǎn)生了utf編碼,utf編碼兼容iso8859-1編碼,同時也可以用來表示所有語言的字符,不過,utf編碼是不定長編碼,每一個字符的長度從1-6個字節(jié)不等。另外,utf編碼自帶簡單的校驗功能。一般來講,英文字母都是用一個字節(jié)表示,而漢字使用三個字節(jié)。
注意,雖然說utf是為了使用更少的空間而使用的,但那只是相對于unicode編碼來說,如果已經(jīng)知道是漢字,則使用GB2312/GBK無疑是最節(jié)省的。不過另一方面,值得說明的是,雖然utf編碼對漢字使用3個字節(jié),但即使對于漢字網(wǎng)頁,utf編碼也會比unicode編碼節(jié)省,因為網(wǎng)頁中包含了很多的英文字符。
3. java對字符的處理
??? 在java應(yīng)用軟件中,會有多處涉及到字符集編碼,有些地方需要進行正確的設(shè)置,有些地方需要進行一定程度的處理。
3.1. getBytes(charset)
??? 這是java字符串處理的一個標準函數(shù),其作用是將字符串所表示的字符按照charset編碼,并以字節(jié)方式表示。注意字符串在java內(nèi)存中總是按unicode編碼存儲的。比如"中文",正常情況下(即沒有錯誤的時候)存儲為"4e2d 6587",如果charset為"gbk",則被編碼為"d6d0 cec4",然后返回字節(jié)"d6 d0 ce c4"。如果charset為"utf8"則最后是"e4 b8 ad e6 96 87"。如果是"iso8859-1",則由于無法編碼,最后返回 "3f 3f"(兩個問號)。
3.2. new String(charset)
??? 這是java字符串處理的另一個標準函數(shù),和上一個函數(shù)的作用相反,將字節(jié)數(shù)組按照charset編碼進行組合識別,最后轉(zhuǎn)換為unicode存儲。參考上述getBytes的例子,"gbk" 和"utf8"都可以得出正確的結(jié)果"4e2d 6587",但iso8859-1最后變成了"003f 003f"(兩個問號)。
因為utf8可以用來表示/編碼所有字符,所以new String( str.getBytes( "utf8" ), "utf8" ) === str,即完全可逆。
3.3. setCharacterEncoding()
??? 該函數(shù)用來設(shè)置http請求或者相應(yīng)的編碼。
對于request,是指提交內(nèi)容的編碼,指定后可以通過getParameter()則直接獲得正確的字符串,如果不指定,則默認使用iso8859-1編碼,需要進一步處理。參見下述"表單輸入"。值得注意的是在執(zhí)行setCharacterEncoding()之前,不能執(zhí)行任何getParameter()。java doc上說明:This method must be called prior to reading request parameters or reading input using getReader()。而且,該指定只對POST方法有效,對GET方法無效。分析原因,應(yīng)該是在執(zhí)行第一個getParameter()的時候,java將會按照編碼分析所有的提交內(nèi)容,而后續(xù)的getParameter()不再進行分析,所以setCharacterEncoding()無效。而對于GET方法提交表單是,提交的內(nèi)容在URL中,一開始就已經(jīng)按照編碼分析所有的提交內(nèi)容,setCharacterEncoding()自然就無效。
??? 對于response,則是指定輸出內(nèi)容的編碼,同時,該設(shè)置會傳遞給瀏覽器,告訴瀏覽器輸出內(nèi)容所采用的編碼。
?
全稱為American Standard Code for Information Interchange,美國信息交換標準代碼,這是世界上最通用的單字節(jié)編碼系統(tǒng),主要用來顯示現(xiàn)代英語及其他西歐語言。
ASCII碼用7位表示,只能表示128個字符,0~31表示控制字符如回車、退格、刪除等;32~126表示打印字符即可以通過鍵盤輸入并且能顯示出來的字符,
其中48~57為0到9十個阿拉伯數(shù)字,65~90為26個大寫英文字母,97~122號為26個小寫英文字母,其余為一些標點符號、運算符號等,具體可以參考ASCII標準表。
轉(zhuǎn)載于:https://www.cnblogs.com/panchanggui/p/9370629.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的ASCII码、ISO8859-1、Unicode、GBK和UTF-8 的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: django入门三(视图)
- 下一篇: ldap集成nginx