汉字乱码_彻底搞懂这烦人的编码与乱码!
我們平時(shí)在處理文本文件或者網(wǎng)絡(luò)請(qǐng)求時(shí),時(shí)不時(shí)會(huì)遇到亂碼的情況,這篇文章就帶你徹底搞懂編碼和亂碼
?首先,我們要知道,在計(jì)算機(jī)中,一切都是用0和1來(lái)表示的。普通的txt文件、或者客戶(hù)端發(fā)過(guò)來(lái)的數(shù)據(jù)等等,這些一切其實(shí)都是通過(guò)0和1轉(zhuǎn)化而來(lái)的。「那它是怎樣從0和1轉(zhuǎn)化我們?nèi)四芸炊淖帜富驖h字呢?」
ASCII
起初,計(jì)算機(jī)是由美國(guó)人發(fā)明的,而且那時(shí)候基本就在美國(guó)運(yùn)行,因此,開(kāi)始只考慮到了美國(guó)的需求,0和1只要能轉(zhuǎn)化成英文字母和符號(hào)就行了,大概需要128個(gè)字符,所以就規(guī)定了0和1轉(zhuǎn)化為這128個(gè)字符的規(guī)則,稱(chēng)作「ASCII編碼」。
計(jì)算機(jī)存儲(chǔ)的最小單位是byte,而1byte有8個(gè)bit位,足夠表示128個(gè)字符(「第一位用0表示,剩下7位從0-127分別表示128個(gè)字符」),因此ASCII編碼就規(guī)定1byte對(duì)應(yīng)一個(gè)英文字符,對(duì)應(yīng)關(guān)系如下圖:
雖然ASCII編碼對(duì)于美國(guó)來(lái)說(shuō)足夠用了,但是其他國(guó)家顯然是不夠的,于是,各個(gè)國(guó)家就發(fā)明了自己的編碼方式,比如我們「中國(guó)的GBK和GB2312等」。但是各個(gè)國(guó)家自己的編碼也都會(huì)兼容ASCII編碼(畢竟人家是鼻祖),前面說(shuō)到ASCII編碼的第一位為0,則其他國(guó)家自己的編碼都會(huì)定義第一位為1,這樣就能區(qū)分當(dāng)前是ASCII編碼還是自己國(guó)家的編碼。
中國(guó)的編碼
對(duì)于美國(guó)而言,一個(gè)字節(jié)就能表示所有的字符,但是在中國(guó)就不行了,光常見(jiàn)的漢字就有好幾千個(gè)了,還不包括符號(hào),因此,中國(guó)首先出現(xiàn)的編碼形式是「GB2312」,它使用兩個(gè)字節(jié)來(lái)表示,這種編碼主要表示的是簡(jiǎn)體中文,不包括繁體字。
后來(lái)在GB2312的基礎(chǔ)上,又發(fā)明了「GBK」編碼(「GB2312表示的字符,用GBK顯示完全一樣」),增加了一萬(wàn)多個(gè)漢字,里面包括繁體字,這就是我們?nèi)粘J褂米畛R?jiàn)的國(guó)內(nèi)編碼。此編碼也是使用兩個(gè)字節(jié)來(lái)表示。
在這里提一下,怎么看一個(gè)字符使用了幾個(gè)字節(jié),可以使用文本編輯器,我這里使用的是EmEditor,當(dāng)然,其他的也行,如果是nodepad++則需要裝一個(gè)插件查看二進(jìn)制。
打開(kāi)EmEditor,雙擊右下角的編碼,選擇GB2312
接著輸入一個(gè)字符,然后再雙擊右下角的編碼,選擇二進(jìn)制(十六進(jìn)制)視圖。
可以看到,使用的是兩個(gè)字節(jié)。這里再提一點(diǎn),「為啥查看二進(jìn)制,很多編輯器默認(rèn)都是顯示的是十六進(jìn)制」?為啥不直接顯示二進(jìn)制,這是因?yàn)?#xff0c;一個(gè)字節(jié)有8個(gè)bit位,而一個(gè)十六進(jìn)制數(shù)字能表示4個(gè)bit位,所以一個(gè)字節(jié)剛好可以使用兩個(gè)十六進(jìn)制來(lái)表示,就像上面顯示的“B9 FA",兩個(gè)表示一個(gè)字節(jié),既簡(jiǎn)單又直觀,如果直接使用二進(jìn)制,要顯示十六個(gè)0或1,眼都要看花掉。
因此,查看字符的二進(jìn)制數(shù)據(jù),最好是通過(guò)十六進(jìn)制來(lái)查看。
世界統(tǒng)一編碼
世界上有很多國(guó)家,每個(gè)國(guó)家都有自己特有的編碼方式,這就導(dǎo)致了編碼不統(tǒng)一,容易造成亂碼的情況。那有什么方式可以讓編碼統(tǒng)一起來(lái)呢?可以通過(guò)「Unicode」。
Unicode和其他編碼方式不一樣,它沒(méi)有規(guī)定字符對(duì)應(yīng)的二進(jìn)制,也沒(méi)有規(guī)定每個(gè)字符占多少個(gè)字節(jié),「它只做了一件事,就是給世界上所有的字符分配了一個(gè)唯一的數(shù)字編號(hào)」,就像人的身份證一樣,這是唯一的,它的范圍從0x000000到0x10FFFF之間(十六進(jìn)制以0x開(kāi)頭,二進(jìn)制以0b開(kāi)頭,八進(jìn)制以0開(kāi)頭),這個(gè)編號(hào)一般寫(xiě)成十六進(jìn)制,前面再加上\u。例如”國(guó)“的Unicode就是”\u56fd“。
那這些編號(hào)怎么對(duì)應(yīng)到二進(jìn)制呢?可以采用UTF-8或者UTF-16和UTF-32等。我們平時(shí)使用的最多的就是「UTF-8」。
UTF-8使用的字節(jié)跟Unicode編號(hào)的大小有關(guān),編號(hào)越大,使用的字節(jié)越多,字節(jié)個(gè)數(shù)在1-4之間。對(duì)于大部分漢字而已,一個(gè)中文字符需要三個(gè)字節(jié)。而且UTF-8兼容ASCII。
亂碼
我們平時(shí)出現(xiàn)亂碼主要有三種情況。
「第一種」:用文本編輯器打開(kāi)一個(gè)文本文件時(shí),顯示亂碼。
這種情況是因?yàn)?#xff0c;我們平時(shí)有時(shí)候文本編輯器設(shè)置了固定UTF-8編碼,但是突然打開(kāi)一個(gè)GBK編碼個(gè)文件,這時(shí)候就會(huì)出現(xiàn)亂碼,里面只有漢字會(huì)亂碼。
解決方法:只要將編輯器的編碼方式設(shè)置成對(duì)應(yīng)的即可。
「第二種」:在程序中讀取文件,出現(xiàn)亂碼。
這種情況是因?yàn)?#xff0c;在程序中讀取文件一般都會(huì)設(shè)置編碼,有時(shí)候省略編碼就會(huì)讀取系統(tǒng)的默認(rèn)編碼,如果設(shè)置的編碼和文件的編碼對(duì)應(yīng)不上就會(huì)出現(xiàn)亂碼。
解決方法:讀取文件時(shí)設(shè)置的編碼和文件編碼保持一致。
「第三種」:接收請(qǐng)求數(shù)據(jù)出現(xiàn)亂碼。
網(wǎng)絡(luò)中傳輸?shù)臄?shù)據(jù)也都是二進(jìn)制數(shù)據(jù),所以在我們傳輸數(shù)據(jù)的時(shí)候,發(fā)送方指定一種編碼將數(shù)據(jù)轉(zhuǎn)成二進(jìn)制通過(guò)網(wǎng)絡(luò)傳輸?shù)浇邮辗?#xff0c;接收方再指定一種編碼將二進(jìn)制數(shù)據(jù)轉(zhuǎn)成字符數(shù)據(jù)。如果發(fā)送方和接收方指定的編碼不一致,則會(huì)出現(xiàn)亂碼情況。
解決方法:發(fā)送方和接收方采用統(tǒng)一編碼即可,一般都是采用UTF-8。
?注意:不論是字符串轉(zhuǎn)二進(jìn)制,還是二進(jìn)制轉(zhuǎn)字符串都需要指定編碼,例如Java中字符串的getBytes()方法將字符串轉(zhuǎn)成字節(jié)數(shù)組,雖然方法可以不傳編碼格式,但內(nèi)部會(huì)傳入系統(tǒng)默認(rèn)編碼Charset.defaultCharset().name()。又比如String(byte bytes[], String charsetName)方法將字節(jié)數(shù)組轉(zhuǎn)成字符串,也依然需要傳入編碼格式,如果不傳就會(huì)采用系統(tǒng)默認(rèn)編碼。
?掃一掃,關(guān)注我
Java面試系列-線程相關(guān)(一)
2020-09-03
Java到底是引用傳遞還是值傳遞
2020-08-07
事務(wù):不好意思,你被隔離了!
2020-07-23
spring事務(wù)咋和新冠病毒一樣,還會(huì)傳染?
2020-07-05
數(shù)據(jù)是怎么一步一步到服務(wù)器的
2020-06-18
總結(jié)
以上是生活随笔為你收集整理的汉字乱码_彻底搞懂这烦人的编码与乱码!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: opencv 检测 键盘_ubuntu+
- 下一篇: 个子矮s弯如何看点打方向图解_S弯如何看