自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

從ASCII、GBK與Unicode等字符編碼角度搞清楚為什么開(kāi)發(fā)中會(huì)出現(xiàn)亂碼問(wèn)題

開(kāi)發(fā) 前端
在SpringBoot中默認(rèn)的字符編碼通常是UTF-8,這是Java和SpringBoot推薦的標(biāo)準(zhǔn)字符編碼(特別是在處理Web請(qǐng)求和響應(yīng))。因?yàn)閁TF-8編碼支持廣泛的字符集,包括大多數(shù)自然語(yǔ)言,并且可以有效地減少數(shù)據(jù)傳輸時(shí)的空間。?

    在我們?nèi)粘5拈_(kāi)發(fā)過(guò)程中經(jīng)常會(huì)出現(xiàn)亂碼問(wèn)題,這種問(wèn)題往往發(fā)生在數(shù)據(jù)的輸入和輸出過(guò)程中。 下面我們從字符編碼的角度來(lái)了解為什么不同的字符編碼之間會(huì)出現(xiàn)亂碼的問(wèn)題。

    我們都知道在計(jì)算機(jī)只存儲(chǔ)和處理的是二進(jìn)制數(shù)據(jù),所有字符(如文字、符號(hào)、數(shù)字)都需要被編碼為二進(jìn)制形式,亂碼其實(shí)是字符的編碼和解碼二進(jìn)制數(shù)據(jù)不匹配導(dǎo)致的問(wèn)題,也就是當(dāng)一個(gè)字符的編碼方式與解碼方式不一致時(shí),解碼結(jié)果會(huì)與預(yù)期不符,呈現(xiàn)出錯(cuò)誤的字符。

1、ASCII碼

    眾所周知,計(jì)算機(jī)是美國(guó)人發(fā)明的,美國(guó)人將他們國(guó)家常用的字符如英文字母、數(shù)字和標(biāo)點(diǎn)符號(hào)等可見(jiàn)字符,還有一些日常使用(如打?。┲猩婕暗降牟豢梢?jiàn)字符(如回車鍵這樣的控制字符)都存儲(chǔ)到計(jì)算機(jī)里面。接下來(lái)他們按照順序?qū)⒉豢梢?jiàn)字符(33個(gè))、可見(jiàn)字符(95個(gè))列出來(lái),于是就形成了如下圖所示的ASCII碼表:

圖片圖片

給0、1、2、a、b.....這樣的字符稱之為ASCII碼字符集;給ASCII碼字符集對(duì)應(yīng)的二進(jìn)制碼稱之為ASCII碼。

    ASCII碼如果在美國(guó)一直使用是沒(méi)有問(wèn)題,但是其他國(guó)家學(xué)習(xí)計(jì)算機(jī)就會(huì)存在問(wèn)題,因?yàn)闆](méi)有對(duì)應(yīng)的字符編碼,于是對(duì)ACSII碼進(jìn)行了擴(kuò)展。

    擴(kuò)展的方法是將原ASCII碼的第一位0修改成第一位為1,然后從128個(gè)字符擴(kuò)展到255個(gè)字符,這樣新增加了128個(gè),給新增加128個(gè)字符取名叫做擴(kuò)展字符集,如下圖所示的擴(kuò)展圖:

圖片圖片

    通過(guò)擴(kuò)展ASCII碼暫時(shí)解決了西方國(guó)家的字符編碼問(wèn)題。隨著計(jì)算機(jī)不斷的發(fā)展和普及,計(jì)算機(jī)走向了世界各國(guó),就比如我們中國(guó)來(lái)說(shuō),中國(guó)的漢字至少有上千個(gè),這個(gè)時(shí)候256個(gè)字符已經(jīng)不夠用了。

2、GB2312碼

    由于8位表示一個(gè)字符已經(jīng)無(wú)法滿足中文字符的實(shí)際需求了,所以就設(shè)計(jì)使用16位表示一個(gè)字符,那么中文怎么編碼呢?編碼的步驟如下所示:

(1)設(shè)定字符集    

    中文字符比較多,采用分區(qū)管理的方式管理中文字符集,共分成94個(gè)區(qū),每個(gè)區(qū)含94個(gè)位,共8836個(gè)碼位。如下所示的第1區(qū)的字符集:

圖片圖片

每個(gè)分區(qū)的存儲(chǔ)的內(nèi)容如下表整理:

分區(qū)范圍

存儲(chǔ)的內(nèi)容

01-09

收錄除漢字外的682個(gè)字符

10-15

用戶自定義符號(hào)區(qū)(未編碼)

16-55

收錄3755個(gè)一級(jí)漢字,按拼音排序

56-87

收錄3008個(gè)二級(jí)漢字,按部首/筆畫(huà)排序

88-94

用戶自定義漢字區(qū)(未編碼)

(2)定義漢字的位置

    每個(gè)分區(qū)的字符如何確定其字符的位置呢?在GB212中使用分區(qū)號(hào)+字符的行列號(hào)來(lái)確定字符的位置,如下圖所示的第16分區(qū)中的”白“字:

圖片圖片

”白“字使用其分區(qū)號(hào)(16)+行號(hào)(3)+ 列號(hào)(7)組成1637

(3)計(jì)算實(shí)際的存儲(chǔ)位置

    將”白“字的碼位1637分別拆分成16、37后轉(zhuǎn)成十六進(jìn)制,然后對(duì)這兩個(gè)十六進(jìn)制數(shù)再分別與A0相加(加A0的好處是讓計(jì)算機(jī)區(qū)分ASCII碼和GB2312碼),將得到的結(jié)果合并就計(jì)算出了”白“字的存儲(chǔ)位置,如下圖所示的計(jì)算過(guò)程:

圖片圖片

通過(guò)這種規(guī)則的計(jì)算,得到”白“字的實(shí)際在計(jì)算機(jī)中存儲(chǔ)位置為0xB0C5。

3、GBK

    由于我們中國(guó)的漢字太多了,導(dǎo)致了很多漢字都不在GB2312碼中,為了滿足實(shí)際的需要,于是對(duì)GB2312碼進(jìn)行擴(kuò)充。

    擴(kuò)充的方法是將之前沒(méi)有用上的碼位都使用上,并且不在規(guī)定它的低位一定要大于127,可以小于127,但是必須要保證高位大于127,然后規(guī)定計(jì)算機(jī)只要遇到大于127的字節(jié)就表示一個(gè)漢字的開(kāi)始。

圖片圖片

    通過(guò)這種方式新增了近2萬(wàn)個(gè)字符和漢字,將這些字符集稱為GBK字符集,對(duì)應(yīng)的編碼稱為GBK碼。

3、Unicode

    中國(guó)可以實(shí)現(xiàn)自己的一套編碼規(guī)則,同樣的道理,其他的國(guó)家也可以實(shí)現(xiàn)自己的一套編碼,這樣就出現(xiàn)了新的問(wèn)題,世界上這么多的編碼,那么不同國(guó)家在進(jìn)行通信的時(shí)候就會(huì)出現(xiàn)亂碼的現(xiàn)象。于是ISO的組織提出了一套規(guī)范,這樣就出現(xiàn)了Unicode的標(biāo)準(zhǔn)。Unicode是一個(gè)標(biāo)準(zhǔn),它包含了字符集以及對(duì)應(yīng)的編碼規(guī)則,目的就是將世界上所有的字符整理到一起并且進(jìn)行編碼。

3.1、UCS-2字符集

    初期Unicode使用16位的UCS-2字符集,UCS-2字符集將世界上所有用到的字符羅列到一起,按照順序標(biāo)上對(duì)應(yīng)的位置編碼然后轉(zhuǎn)成二進(jìn)制存儲(chǔ),這樣UCS-2字符集可以表示65536個(gè)字符。如下圖所示的UCS-是字符集:

圖片圖片

3.2、UCS-4字符集

    UCS-2字符集還是無(wú)法表示世界上所有的語(yǔ)言字符,于是Unicode推出了UCS-4字符集,UCS-4字符集用32位表示一個(gè)字符,如下圖所示:

圖片圖片

    UCS-4字符集可以表示近42億個(gè)字符,基本可以容納世界上所有的字符了,由于UCS-4字符集占用的空間大,所以它沒(méi)有被各國(guó)很好的接受。

3.3、UTF-8編碼

    到了互聯(lián)網(wǎng)飛速發(fā)展的階段,世界各國(guó)的交流日益頻繁,不同的編碼之間無(wú)法通信,大家便重新思考unicode編碼,于是便推出如下的編碼規(guī)則:

圖片圖片

    UTF-32屬于定長(zhǎng)編碼,它的每個(gè)字符編碼固定占4字節(jié),比如對(duì)于英文字母a,UTF-32表示這個(gè)字符需要32位,在ASCII的編碼中字符a只需8位就可以表示,那么那如果存儲(chǔ)的內(nèi)容主要是英文,使用UTF-32占用的存儲(chǔ)空間就是使用ASCII編碼占用的存儲(chǔ)空間的四倍。

    UTF-32編碼會(huì)造成嚴(yán)重的內(nèi)存消耗,而UTF-8編碼則不存在這個(gè)問(wèn)題,因?yàn)樗且环N變長(zhǎng)的編碼,對(duì)于英文字符UTF8和ASCII編碼是一樣的,只占一個(gè)字節(jié),對(duì)于非英文的字符,UTF-8會(huì)使用2~4個(gè)字節(jié)來(lái)表示(如對(duì)于中文一般會(huì)使用三個(gè)字節(jié)來(lái)表示)。

    UTF-8的優(yōu)勢(shì)是可以有效的利用存儲(chǔ)空間避免浪費(fèi),并且UTF-8向后兼容了ASCII編碼,UTF-8的編碼規(guī)則有如下的幾種:

圖片圖片

    1個(gè)字節(jié)的UTF-8編碼,它的最高位固定為0,剩余的七位用來(lái)編碼,這和ASCII編碼是完全一樣的,所以為什么UTF-8可以兼容了ASCII就是這個(gè)原因。

    2個(gè)字節(jié)的UTF-8編碼的首字節(jié)的前三位為110,其余字節(jié)的開(kāi)頭兩位為10。

    3個(gè)字節(jié)的UTF-8編碼的首字節(jié)的前四位為1110,其余字節(jié)的開(kāi)頭兩位是10

    4個(gè)字節(jié)的UTF-8編碼首字節(jié)的前五位為11110,其余四節(jié)的開(kāi)頭是10。

    從UTF-8的編碼規(guī)則我們可以看到對(duì)于2字節(jié)到4字節(jié)的編碼,它的首字節(jié)開(kāi)頭有幾個(gè)連續(xù)的1,那就代表著它這個(gè)編碼占了幾個(gè)字節(jié),那這樣解碼的時(shí)候就知道如何對(duì)這個(gè)二進(jìn)制數(shù)據(jù)進(jìn)行解碼。

    那么一個(gè)漢字是如何轉(zhuǎn)成UTF-8編碼呢?以中文的這個(gè)”王“字為例,它在UCS-4中的編碼是0x0000 738B,其UTF-8的編碼過(guò)程如下所示:

圖片圖片

    注意的是,如果漢字的二進(jìn)制無(wú)法填滿模板的所有的x空位,則剩余的空位默認(rèn)都用0來(lái)填充,通過(guò)這種方式填充完以后就得到了漢字中所對(duì)應(yīng)的UTF-8的編碼。同樣要解碼的話,也只需要逆序執(zhí)行一次就可以得到對(duì)應(yīng)的漢字。

    至此我們了解了編碼的發(fā)展過(guò)程,由于每種編碼都有自己的規(guī)則,如果不按照它的規(guī)則進(jìn)行解碼就得到一串亂碼。

    在SpringBoot中默認(rèn)的字符編碼通常是UTF-8,這是Java和SpringBoot推薦的標(biāo)準(zhǔn)字符編碼(特別是在處理Web請(qǐng)求和響應(yīng))。因?yàn)閁TF-8編碼支持廣泛的字符集,包括大多數(shù)自然語(yǔ)言,并且可以有效地減少數(shù)據(jù)傳輸時(shí)的空間。

責(zé)任編輯:武曉燕 來(lái)源: 龍蝦編程
相關(guān)推薦

2017-08-15 08:27:48

云備份問(wèn)題恢復(fù)

2020-12-16 11:09:27

JavaScript語(yǔ)言開(kāi)發(fā)

2011-06-22 09:37:03

桌面虛擬化存儲(chǔ)

2020-11-16 08:37:16

MariaDB性能優(yōu)化

2010-06-04 16:12:39

MYSQL_ASSOC

2020-04-28 17:26:04

監(jiān)督學(xué)習(xí)無(wú)監(jiān)督學(xué)習(xí)機(jī)器學(xué)習(xí)

2020-12-31 07:57:25

JVM操作代碼

2021-09-29 19:17:51

編碼URLEncodeGBK

2015-10-12 10:01:26

AndroidWindows應(yīng)用Windows 10

2021-09-01 09:32:40

工具

2018-06-26 14:42:10

StringJava數(shù)據(jù)

2018-06-20 10:43:58

云端霧端霧計(jì)算

2021-01-19 06:43:10

Netty框架網(wǎng)絡(luò)技術(shù)

2010-03-24 11:37:22

Python unic

2022-06-13 10:07:13

物聯(lián)網(wǎng)開(kāi)發(fā)物聯(lián)網(wǎng)

2022-11-16 14:02:44

2021-02-06 12:28:53

低代碼開(kāi)發(fā)者數(shù)字化

2022-10-24 00:33:59

MySQL全局鎖行級(jí)鎖

2011-03-07 17:44:59

中小企業(yè)實(shí)施虛擬化

2020-04-11 11:21:22

留存分析模型分析
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)