詳細(xì)內(nèi)容來自:
Unicode(UTF-8, UTF-16)令人混淆的概念
Java 語言中一個(gè)字符占幾個(gè)字節(jié)?(知乎)
unicode和UTF
1.unicode:統(tǒng)一的字符編號(hào),僅僅提供字符與編號(hào)間的映射。由于歷史遺留及口語化原因,說起unicode,也常指UTF-16。
2.UTF:unicode transformation format ,即unicode具體的實(shí)現(xiàn)方式。
(1)UTF-16:
舊標(biāo)準(zhǔn)中:這個(gè)“16”意思為固定使用16位(即2字節(jié))儲(chǔ)存一個(gè)字符。0-127就是ASCII那些,128-65536就是擴(kuò)充的那些字符,很容易理解。
新標(biāo)準(zhǔn)中:使用16位/32位來儲(chǔ)存一個(gè)字符,不再是定長的16位。這里要注意,意思是在UTF-16編碼下,可能解析一個(gè)字符時(shí)讀取2個(gè)字節(jié)來解析,但下一個(gè)字符讀取4個(gè)字節(jié)來解析。新標(biāo)準(zhǔn)中,UTF-16也變成不定長的編碼了。
(2)UTF-8:這個(gè)“8”意思為8位為一塊(說了等于沒說系列)。
這個(gè)“8”很容易誤導(dǎo)人。實(shí)際上它是不定長編碼,使用8位/16位/24位/32位來儲(chǔ)存一個(gè)字符。
(3)UTF-32:固定使用32位儲(chǔ)存一個(gè)字符,是定長編碼。
3.c++中字符char的問題:
(1)char c='中'; 將發(fā)生截?cái)?,c中并不是儲(chǔ)存著這個(gè)'中'。
首先編譯器將檢測(cè)你的系統(tǒng)默認(rèn)編碼(如GBK),把這個(gè)'中'轉(zhuǎn)換為一個(gè)int的值(int占4字節(jié),足夠表示了),然后把這個(gè)int強(qiáng)制轉(zhuǎn)換為char,賦值給c,發(fā)生截?cái)?。這里可見,c++不能使用一個(gè)char來儲(chǔ)存一個(gè)中文字符。
(2)char arr[3]="中" 正確。
編譯器處理時(shí),將使用兩個(gè)字節(jié)( char[0]和char[1] )來儲(chǔ)存'中'(對(duì)應(yīng)的int的低16位),同時(shí)為char[2]賦值'\0'。即此時(shí)必須借助char數(shù)組
4.java中char的問題:
(1)java中字符占2字節(jié),與c++的不同
(2)java內(nèi)部編碼采用UTF-16。但是新標(biāo)準(zhǔn)中UTF-16是不定長編碼,一個(gè)字符可能為2/4字節(jié),所以實(shí)際上java中char依然有這個(gè)問題。如果某個(gè)字符需要4字節(jié),那么將發(fā)生截?cái)?,?字節(jié)將被賦值到char中。實(shí)際上4字節(jié)的那些字符,很難打出來的,一般能輸入進(jìn)去的話都沒問題。
(3)String類由char[]當(dāng)儲(chǔ)存結(jié)構(gòu),但是屏蔽了UTF-16不定長造成的差異。也就是說如果一個(gè)字符串由兩個(gè)4字節(jié)的字符組成,那么String.length依然為2,且此時(shí)打印String依然能正確輸出。詳細(xì)看一開始就貼出來的鏈接。
(4)內(nèi)部編碼和外部編碼:
內(nèi)碼是程序內(nèi)部使用的字符編碼,特別是某種語言實(shí)現(xiàn)其char或String類型在內(nèi)存里用的內(nèi)部編碼;
外碼是程序與外部交互時(shí)外部使用的字符編碼?!巴獠俊毕鄬?duì)“內(nèi)部”而言;不是char或String在內(nèi)存里用的內(nèi)部編碼的地方都可以認(rèn)為是“外部”。
詳細(xì)看一開始就貼出來的鏈接。
5.編碼
unicode編碼表中的第20013號(hào)字符為'中',其中
(1)UTF-16BE(BE意思為大端):
很簡單,直接把十進(jìn)制的20013用16位二進(jìn)制表示即可:
01001110 00101101
(2)UTF-8:
建議自行去了解UTF-8的規(guī)則。這里顯然需要三個(gè)字節(jié)的格式1110xxxx 10xxxxxx 10xxxxxx,把對(duì)應(yīng)的二進(jìn)制填入即可:
11100100 10111000 10101101
(3)你值得擁有的查看unicode編碼的網(wǎng)站:Unicode?字符百科

url編碼
問題:http://localhost?a=1&b=2,url中的查詢參數(shù)是什么?
很明顯是a=1和b=2。但為什么不理解為a= "1&b=2"這個(gè)字符串呢?
這問題出在&這個(gè)字符,跟我們字符串的反斜杠\差不多道理,&是一個(gè)特殊意義的符號(hào)。后端將把這個(gè)字符當(dāng)作分割用的標(biāo)記(=、?和其他符號(hào)基本同理)。
也就是如果我們需要傳送a= "1&b=2"時(shí),應(yīng)該寫成http://localhost?a=1%26b%3D2。其中%26就表示&,%3D就表示=,更多轉(zhuǎn)義可以查看url編碼規(guī)則。
1.urlencoded:
url編碼是基于unicode/GBK等編碼的一種編碼方式,以解決上面提到的和其他(中文傳輸)問題。
一個(gè)最簡單的例子,如前面例子字符串"中"的UTF-8編碼為E4 B8 AD,那么urlencoded后,就是字符串%E4%B8%AD。如果是基于UTF-16BE,那么urlencoded后就是字符串%4E%2D。
顯然,對(duì)不同編碼的字符(如中文),urlencoded出來的結(jié)果可能有所不同。而對(duì)于&=?這些特殊符號(hào),編碼規(guī)則是一定的
2.application/x-www-form-urlencoded
是http頭content-type的可選值之一,意味著當(dāng)前請(qǐng)求參數(shù)/實(shí)體內(nèi)容進(jìn)行過urlencoded。此外application/x-www-form-urlencoded; charset=UTF-8表明這個(gè)urlencoded是基于UTF-8編碼的,避免解碼時(shí)出錯(cuò)。
3.post方式時(shí)
(1)application/x-www-form-urlencoded; charset=UTF-8
描述如上,請(qǐng)了解瀏覽器表單默認(rèn)自動(dòng)編碼提交和自己手動(dòng)提交的區(qū)別,避免進(jìn)行兩次urlencoded或沒有urlencoded
(2)application/json; charset=UTF-8
沒有進(jìn)行url編碼。因?yàn)榇藭r(shí)后端不需要&符號(hào)來做分隔符,直接傳json字符串就是
(3)multipart/form-data
沒有進(jìn)行url編碼。因?yàn)榇藭r(shí)后端不需要&符號(hào)來做分隔符,而是使用一種特殊分隔符,詳細(xì)右轉(zhuǎn)百度