(一)在UTF-8中,一個漢字為什么需要三個字節?
UNICODE是萬能編碼,包含了所有符號的編碼,它規定了所有符號在計算機底層的二進制的表示順序。有關Unicode為什么會出現就不敘述了,Unicode是針對所有計算機的使用者定義一套統一的編碼規范,這樣計算機使用者就避免了編碼轉換的問題。Unicode定義了所有符號的二進制形式,也就是符號如何在計算機內部存儲的,而且每個符號規定都必須使用兩個字節來表示,也就是用16位二進制去代表一個符號,這樣就導致了一個問題,英文編碼的空間浪費,因為在ANSI中的符號都是一個字節來表示的,而使用了UNICODE編碼就白白浪費了一個字節。也就代表着Unicode需要使用兩倍的空間去存儲相應的ANSI編碼下的符號。雖然現在硬盤或者內存都很廉價,但是在網絡傳輸中,這個問題就凸顯出來了,你可以這樣想想,本來1M的帶寬在ANSI下可以代表1024*1024個字符,但是在Unicode下卻只能代表1024*1024/2個字符。也就是1MB/s的帶寬只能等價於512KB/s,這個很可怕啊。所以為了解決符號在網絡中傳輸的浪費問題,就出現了UTF-8編碼,Unicode transfer format -8 ,后面的8代表是以8位二進制為單位來傳輸符號的,但是這樣又導致了一個問題,雖然UTF-8可以使用一個字節來表示ANSI下的符號,但是對於其它類似漢語的符號,得需要兩個字節來表示,所以計算機不知道如何去截取一個符號,也就是一個符號對應的二進制的截取開始位置和截取結束位置。所以為了解決Unicode下的ANSI符號的空間浪費和網絡傳輸下如何截取字符的問題,UTF規定:如果一個符號只占一個字節,那么這個8位字節的第一位就為0。如果為兩個字節,那么規定第一個字節的前兩位都為1,然后第一個字節的第三位為0,第二個字節的前兩位為10,然后如果是三個字節的話,那么第一個字節的前三位為111,第四位為0,剩余的兩個字節的前兩位都為10。按照這樣的算法去思考一個中文字符的UTF-8是怎么表示的:一個中文字符需要兩個字節來表示,兩個字節一共是16位,那么UTF-8下,兩個字節是不夠的,因為兩個字節下,第一個字節已經占據了三位:110,然后剩余的一個字節占據了兩位:10,現在就只剩下8位,與Unicode下的兩個字節,16位去表示任意一個字符是相悖的,也就是Unicode下的16位減去UTF-8下的8位=8位,剛好差了一個字節的空間,所以就使用三個字節去表示非ANSI字符:三個字節下,一共是24位,第一個字節頭四位是:1110,后兩個字節的前兩位都是:10,那么24位-8位=16位,剛好兩個字節去表示Unicode下的任意一個非ANSI字符。這也就是為什么UTF-8需要使用三個字節去表示一個非ANSI字符的原因了!
多個字節提供的位數超過了所需要的,多余的位以0補全到編碼前面
轉自:https://blog.csdn.net/crslee/article/details/52041016
(二)英文字母和中文漢字在不同字符集編碼下的字節數
英文字母:
字節數 : 1;編碼:GB2312
字節數 : 1;編碼:GBK
字節數 : 1;編碼:GB18030
字節數 : 1;編碼:ISO-8859-1
字節數 : 1;編碼:UTF-8
字節數 : 4;編碼:UTF-16
字節數 : 2;編碼:UTF-16BE
字節數 : 2;編碼:UTF-16LE
中文漢字:
字節數 : 2;編碼:GB2312
字節數 : 2;編碼:GBK
字節數 : 2;編碼:GB18030
字節數 : 1;編碼:ISO-8859-1
字節數 : 3;編碼:UTF-8
字節數 : 4;編碼:UTF-16
字節數 : 2;編碼:UTF-16BE
字節數 : 2;編碼:UTF-16LE
這是個好問題,可以當作一個筆試題。先從字符編碼講起。
1、美國人首先對其英文字符進行了編碼,也就是最早的ascii碼,用一個字節的低7位來表示英文的128個字符,高1位統一為0;
2、后來歐洲人發現尼瑪你這128位哪夠用,比如我高貴的法國人字母上面的還有注音符,這個怎么區分,得,把高1位編進來吧,這樣歐洲普遍使用一個全字節進行編碼,最多可表示256位。歐美人就是喜歡直來直去,字符少,編碼用得位數少;
3、但是即使位數少,不同國家地區用不同的字符編碼,雖然0--127表示的符號是一樣的,但是128--255這一段的解釋完全亂套了,即使2進制完全一樣,表示的字符完全不一樣,比如135在法語,希伯來語,俄語編碼中完全是不同的符號;
4、更麻煩的是,尼瑪這電腦高科技傳到中國后,中國人發現我們有10萬多個漢字,你們歐美這256字塞牙縫都不夠。於是就發明了GB2312這些漢字編碼,典型的用2個字節來表示絕大部分的常用漢字,最多可以表示65536個漢字字符,這樣就不難理解有些漢字你在新華字典里查得到,但是電腦上如果不處理一下你是顯示不出來的了吧。
5、這下各用各的字符集編碼,這世界咋統一?俄國人發封email給中國人,兩邊字符集編碼不同,尼瑪顯示都是亂碼啊。為了統一,於是就發明了unicode,將世界上所有的符號都納入其中,每一個符號都給予一個獨一無二的編碼,現在unicode可以容納100多萬個符號,每個符號的編碼都不一樣,這下可統一了,所有語言都可以互通,一個網頁頁面里可以同時顯示各國文字。
6、然而,unicode雖然統一了全世界字符的二進制編碼,但沒有規定如何存儲啊,親。x86和amd體系結構的電腦小端序和大端序都分不清,別提計算機如何識別到底是unicode還是acsii了。如果Unicode統一規定,每個符號用三個或四個字節表示,那么每個英文字母前都必然有二到三個字節是0,文本文件的大小會因此大出二三倍,這對於存儲來說是極大的浪費。這樣導致一個后果:出現了Unicode的多種存儲方式。
7、互聯網的興起,網頁上要顯示各種字符,必須統一啊,親。utf-8就是Unicode最重要的實現方式之一。另外還有utf-16、utf-32等。UTF-8不是固定字長編碼的,而是一種變長的編碼方式。它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。這是種比較巧妙的設計,如果一個字節的第一位是0,則這個字節單獨就是一個字符;如果第一位是1,則連續有多少個1,就表示當前字符占用多少個字節。
8、注意unicode的字符編碼和utf-8的存儲編碼表示是不同的,例如"嚴"字的Unicode碼是4E25,UTF-8編碼是E4B8A5,這個7里面解釋了的,UTF-8編碼不僅考慮了編碼,還考慮了存儲,E4B8A5是在存儲識別編碼的基礎上塞進了4E25。
4E25的二進制位 0100,1110,0010,0101 中文漢字在utf-8中到底占幾個字節,一般是3個字節(原因見第一章),最常見的編碼方式是1110xxxx 10xxxxxx 10xxxxxx。組合起來為 1110,0100,1011,1000,1010,0101 =E4B8A5
9、UTF-8 使用一至四個字節為每個字符編碼。128 個 ASCII 字符(Unicode 范圍由 U+0000 至 U+007F)只需一個字節,帶有變音符號的拉丁文、希臘文、西里爾字母、亞美尼亞語、希伯來文、阿拉伯文、敘利亞文及馬爾代夫語(Unicode 范圍由 U+0080 至 U+07FF)需要二個字節,其他基本多文種平面(BMP)中的字符(CJK屬於此類-Qieqie注)使用三個字節,其他 Unicode 輔助平面的字符使用四字節編碼。
10、最后,要回答你的問題,常規來看,中文漢字在utf-8中到底占幾個字節,一般是3個字節,最常見的編碼方式是1110xxxx 10xxxxxx 10xxxxxx。
轉自:https://blog.csdn.net/u010737354/article/details/52456570