九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
編程基礎之編碼與解碼
關于編碼與解碼無論是編程還是日常的電腦使用都是避不開的,但是一般也沒人會特意注意到這些,只有在某些特定場合下出現(xiàn)亂碼的時候,才會根據(jù)網(wǎng)上教程修改一下編碼格式。
在這里簡單介紹一下相關的基礎知識,讓大家在知道怎么做的基礎上,知道為什么要這樣做。
此篇文章內容為黑馬程序員關于編碼與解碼的學習筆記,B站上也有相關視頻。大約三小時左右,大家看完文章如果覺得有興趣的話,可以去B站看一下視頻講解,鏈接我會貼在文章末尾。
文章將會以下面思維導圖進行展開敘述,可能有點長

什么是編碼與解碼

因為計算機底層只能存儲01,  稱為一個bit,8個bit組成一個字節(jié)。

所以存儲類似于漢字、英文字符、符號字符等內容需要一個編碼表,實現(xiàn)從字節(jié)到符號的轉換。

從顯示器上的字符到計算機中的字節(jié)稱為編碼

從計算機上的字節(jié)到顯示器上的字符稱為解碼。

二進制書寫起來太麻煩,所以一般都用十六進制表示碼值

常見編碼表 ASCII

計算機發(fā)明的時候,基本只考慮了美國的需求,大概只需要128個字符,所以使用的是ASCII

其中編碼的 32-126 表示可打印字符


0-31和127表示不可打印字符,下圖列舉一部分


水平制表符表示一個Tab

但是ASCII碼表只對美國夠用,于是各個國家的計算機廠商發(fā)明了各種各樣的編碼方式表示自己國家的字符。

西歐國家流行的是ISO 8859-1Windows-1252。

在中國是GB2312、GBK、GB18030Big5。

常見編碼表 ISO-8859-1

ISO 8859-1又稱Latin-1,它也是使用一個字節(jié)表示一個字符。

因為西歐的文字也都是字母拼接,只不過不是26個英文字母罷了,其中0到127與ASCII一樣,128到255規(guī)定了不同的含義。

在128到255中,128到159表示一些控制字符,這些字符也不常用。

其中160到255表示一些西歐字符,如下圖所示:


常見編碼表 windows-1252

ISO 8859-1雖然號稱是標準,用于西歐國家,但它連歐元()這個符號都沒有,因為歐元比較晚,而標準比較早。

實際使用中更為廣泛的是Windows-1252編碼,這個編碼與ISO 8859-1基本是一樣的,區(qū)別只在于數(shù)字128到159。

Windows-1252使用其中的一些數(shù)字表示可打印字符,這些數(shù)字表示的含義,如下圖所示:

這個編碼中加入了歐元符號以及一些其他常用的字符?;旧峡梢哉J為,ISO 8859-1已被Windows-1252取代。

HTML5甚至明確規(guī)定,如果文件聲明的是ISO 8859-1編碼,它該被看做Windows-1252編碼。

常見編碼表 GB2312

美國和西歐字符用一個字節(jié)就夠了,但中文顯然是不夠的。

中文第一個標準是GB2312,而且GB2312標準主要針對的是簡體中文常見字符,包括約7000個漢字,不包括一些罕見詞,不包括繁體字。

GB2312固定使用兩個字節(jié)表示漢字,在這兩個字節(jié)中,最高位都是1,如果是0,就認為是ASCII字符。

在這兩個字節(jié)中: 
第一個字節(jié)范圍是10100001(十進制161) 到 11110111(十進制247)。
第二個字節(jié)范圍是10100001(十進制161) 到 11111110(十進制254)。

常見編碼表 GBK

GBK建立在GB2312的基礎上,向下兼容GB2312。

也就是說,GB2312編碼的字符的二進制表示,在GBK編碼里是完全一樣的。

GBK增加了一萬四千多個漢字,共計約21000漢字,其中包括繁體字。

GBK同樣使用固定的兩個字節(jié)表示:
第一個字節(jié)范圍是10000001(十進制129) 到 11111110(十進制254)。
第二個字節(jié)范圍是0100000(十進制64) 到 01111110(十進制126) 和 10000000(十進制128) 到 11111110(十進制254)。

需要注意的是,第二個字節(jié)是從64開始的(64屬于第一個bit為 0 的情況,和ASCII的編碼重合了),也就是說,第二個字節(jié)最高位可能為0。

那怎么知道它是漢字的一部分,還是一個ASCII字符呢?

其實很簡單,因為漢字是用固定兩個字節(jié)表示的,在解析二進制流的時候,如果第一個字節(jié)的最高位為1,那么就將下一個字節(jié)讀進來一起解析為一個漢字,而不用考慮它的最高位,解析完后,跳到第三個字節(jié)繼續(xù)解析。

所以第二個字節(jié)從64開始是不會影響解碼的,但第一個字節(jié)一定不能以 0 開頭。

常見編碼表 GB18030

GB18030向下兼容GBK,增加了五萬五千多個字符,共七萬六千多個字符。

包括了很多少數(shù)民族字符,以及中日韓統(tǒng)一字符。

用兩個字節(jié)已經(jīng)表示不了GB18030中的所有字符,GB18030使用變長編碼,有的字符是兩個字節(jié),有的是四個字節(jié)。

在兩字節(jié)編碼中,字節(jié)表示范圍與GBK一樣。

在四字節(jié)編碼中: 
第一個字節(jié)的值從10000001 (十進制129) 到 11111110(十進制254)。
第二個字節(jié)的值從00110000 (十進制48) 到 00111001(十進制57)。
第三個字節(jié)的值從10000001 (十進制129) 到 11111110(十進制254)。
第四個字節(jié)的值從00110000 (十進制48) 到 00111001(十進制57)。

解析二進制時,如何知道是兩個字節(jié)還是四個字節(jié)表示一個字符呢?

很簡單,看第二個字節(jié)的范圍,如果是48到57就是四個字節(jié)表示,因為兩個字節(jié)編碼中第二字節(jié)都比這個大。

所以這樣綜合說明GB18030兼容GBK,兼容GB2312,兼容ASCIl

但是GB18030,GBK,GB2312這三個編碼ISO8859-1是不兼容的哦。

常見編碼表 Big5

Big5是針對繁體中文的,廣泛用于臺灣香港等地。

Big5包括1萬3千多個繁體字,和GB2312類似,一個字符同樣固定使用兩個字節(jié)表示。

在這兩個字節(jié)中: 
第一個字節(jié)范圍是10000001(十進制129) 到 11111110(十進制254)。
第二個字節(jié)范圍是01000000(十進制64)到 01111110(十進制126)和10100001(十進制161) 到 1111 1110 (十進制254)。

Big5GB18030GBK,GB2312不兼容。

如果已經(jīng)理解了上文,其實就能理解為什么Big5GB的三個編碼為什么不兼容了。

編碼表匯總

ASCII碼是基礎,一個字節(jié)表示,最高位設為0,其他7位表示128個字符。

其他編碼都是兼容ASCII的,最高位使用1來進行區(qū)分。

西歐主要使用Windows-1252,使用一個字節(jié),增加了額外128個字符。

中文大陸地區(qū)的三個主要編碼GB2312,GBK,GB18030,有時間先后關系,表示的字符數(shù)越來越多,且后面的兼容前面的,GB2312GBK都是用兩個字節(jié)表示,而GB18030則使用兩個或四個字節(jié)表示。

香港臺灣地區(qū)的主要編碼是Big5

如果文本里的字符都是ASCII碼字符,那么采用以上所說的任一編碼方式都是一樣的,不會亂碼。

但如果有高位為1的字符,除了GB2312/GBK/GB18030外,其他編碼都是不兼容的。

比如,Windows-1252和中文的各種編碼是不兼容的,即使Big5GB18030都能表示繁體字,其表示方式也是不一樣的,而這就會出現(xiàn)所謂的亂碼。

常見編碼表 Unicode

產(chǎn)生原因:

每個國家的各種計算機廠商都對自己常用的字符進行編碼,在編碼的時候基本忽略了別的國家的字符和編碼,甚至忽略了同一國家的其他計算機廠商,這樣造成的結果就是,出現(xiàn)了太多的編碼,且互相不兼容。

Unicode 做了一件事,就是給世界上所有字符都分配了一個唯一的數(shù)字編號,這個編號范圍從0x000000到0X10FFFF,包括110多萬。

Unicode 中文翻譯 統(tǒng)一碼 。

但大部分常用字符都在0x0000到0XFFFF之間,即65536個數(shù)字之內。

每個字符都有一個Unicode編號,這個編號一般寫成16進制,在前面加U+。

大部分中文的編號范圍在U+4E00到U+9FA5。

1990年開始研發(fā),1994年正式公布。
隨著計算機工作能力的增強,Unicode也在面世以來的十多年里得到普及。
Unicode6.3版已發(fā)布(2013年11月)。在Unicode聯(lián)盟網(wǎng)站上可以查看完整的6.3的核心規(guī)范。
Unicode定義了大到足以代表人類所有可讀字符的字符集。
Unicode其實應該是一個碼值表。Unicode的功用是為每一個字符提供一個唯一的數(shù)字碼。而對數(shù)字碼的存儲規(guī)則的定義則需要依靠UTF-8/UTF-16/UTF-32
UTF-8/UTF-16/UTF-32是通過對Unicode碼值進行對應規(guī)則轉換后。編碼保持到內存/文件中。UTF-8/UTF-16都是可變長度的編碼方式。

Unicode就做了這么一件事,就是給所有字符分配了唯一數(shù)字編號。

它并沒有規(guī)定這個編號怎么對應到二進制表示。

這是與上面介紹的其他編碼不同的,其他編碼都既規(guī)定了能表示哪些字符,又規(guī)定了每個字符對應的二進制是什么,而Unicode本身只規(guī)定了每個字符的數(shù)字編號是多少。

那編號怎么對應到二進制表示呢?

有多種方案,主要有UTF-32,UTF-16和UTF-8

UTF-32編碼

字符編號的整數(shù)二進制形式,四個字節(jié)但這里四個字節(jié)的存儲會有一個大小端的問題。

“大端”稱為(Big Endian,BE),'小端”稱為(Little Endian,LE) 

比如:


注意:

之所以有大端和小端兩種方式,是因為硬件讀寫順序的不同。

大端:數(shù)據(jù)的高字節(jié)保存在內存的低地址中,低字節(jié)保存到內存的高地址中,和我們的閱讀習慣一致;小端則相反。

常用的X86結構是小端模式。arm支持大小端可配置 

采用大端方式進行數(shù)據(jù)存放符合人類的正常思維,而采用小端方式進行數(shù)據(jù)存放利于計算機處理。

UTF-16編碼

在了解UTF-16編碼方式之前,先了解一下另外一個概念——'平面'。

在上面的介紹中,提到了Unicode是一本很厚的字典,它將全世界所有的字符定義在一個集合里。

這么多的字符不是一次性定義的,而是分區(qū)定義。

每個區(qū)可以存放65536個(2^16)字符,稱為一個平面(plane)。

目前,一共有17個(小于2^5)平面(65536*17=1114112 也就是110多萬),也就是說,整個Unicode字符集的大小現(xiàn)在是2^21

最前面的65536個字符位,稱為基本平面(簡稱BMP),它的碼點范圍是從0到2^16-1,寫成16進制就是從U+0000到U+FFFF。

所有最常見的字符都放在這個平面,這是Unicode最先定義和公布的一個平面。

剩下的字符都放在輔助平面(簡稱SMP),碼點范圍從U+010000到U+10FFFF。

基本了解了平面的概念后,再說回到UTF-16。

UTF-16編碼介于UTF-32與UTF-8之間,同時結合了定長和變長兩種編碼方法的特點。
它的編碼規(guī)則很簡單:基本平面的字符占用2個字節(jié),輔助平面的字符占用4個字節(jié)。
也就是說,UTF-16的編碼長度要么是2個字節(jié)(U+0000到U+FFFF),要么是4個字節(jié)(U+010000到U+10FFFF)。
那么問題來了,當我們遇到兩個字節(jié)時,到底是把這兩個字節(jié)當作一個字符還是與后面的兩個字節(jié)一起當作一個字符呢?
為了將兩個字節(jié)的UTF-16編碼與四個字節(jié)的UTF-16編碼區(qū)分開來。
Unicode編碼的設計者將基本平面的 0xD800 - 0xDFFF 保留下來,稱為代理區(qū)(Surrogate):
輔助平面的字符位共有2^20個,因此表示這些字符至少需要20個二進制位。
UTF-16將這20個二進制位分成兩半,前10位映射在U+D800到U+DBFF,稱為高代理位(H),后10位映射在U+DCO0到U+DFFE,稱為低代理位(L)。
這意味著,一個輔助平面的字符,被拆成兩個基本平面的字符表示。

如果 U>0x10000,我們先計算U=U-0x10000,然后將U寫成二進制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16編碼(二進制)就是:110110yyyyyyyyyy110111xxxxxxxxxx

按照上述規(guī)則,Unicode編碼0X10000-0×10FFFF的UTF-16編碼有四個字節(jié),前兩個字節(jié)的高6位是110110,后兩個字節(jié)的高6位是110111。

可見,前兩個字節(jié)的取值范圍(二進制)是1101100000000000到1101101111111111,即QXD800-0xDBFF。

后兩個字節(jié)取值范圍(一進制)是1101110000000000到1101111111111111,即OXDCOO-0XDFFE。

因此,當我們遇到兩個字節(jié),發(fā)現(xiàn)它的碼點在U+D800到U+DBFE之間,就可以斷定,緊跟在后面的兩個字節(jié)的碼點,應該在U+DC00到U+DFFE之間,這四個字節(jié)必須放在一起解讀。

舉例說明:

UTF-32一樣,UTF-16也有UTF-16LE(小端)和UTF-16BE(大端)之分

注意:

UTF-16常用于系統(tǒng)內部編碼,我們平常說的“Unicode編碼是2個字節(jié)”這句話,其實是因為windows系統(tǒng)默認的Unicode編碼就是UTF-16。

在常用基本字符上2個字節(jié)的編碼方式已經(jīng)夠用導致的誤解,其實是可變長度的。

在沒有特殊說明的情況下,常說的Unicode編碼可以理解為UTF-16編碼,而且是UTF-16BE(大端)編碼

UTF-16UTF-32節(jié)省了很多空間,但是任何一個字符都至少需要兩個字節(jié)表示,對于美國和西歐國家而言,還是很浪費的。所以就出現(xiàn)了UTF-8

UTF-8編碼

UTF-8就是使用變長字節(jié)表示,每個字符使用的字節(jié)個數(shù)與其Unicode編號的大小有關,編號小的使用的字節(jié)就少,編號大的使用的字節(jié)就多,使用的字節(jié)個數(shù)從1到4個不等。

具體來說,各個Unicode編號范圍對應的二進制格式模板

如下圖所示:

圖中的x表示可以用的二進制位,而每個字節(jié)開頭的1或0是固定的。

小于128的(即OX00-0X7F之間的字符),編碼與ASCII碼一樣,最高位為0。

其他編號的第一個字節(jié)有特殊含義,最高位有幾個連續(xù)的1表示一共用幾個字節(jié)表示,而其他字節(jié)都以10開頭。

4字節(jié)模板有21個x,即可以容納21位二進制數(shù)字。

Unicode的最大碼位0×10FFFF也只有21位。

舉例說明:

注意:UTF-8UTF-32/UTF-16不同的地方是UTF-8是兼ASCII的,對大部分中文而言,一個中文字符需要用三個字節(jié)表示。

UTF-8的優(yōu)勢是網(wǎng)絡上數(shù)據(jù)傳輸英文字符只需要1個字節(jié),可以節(jié)省帶寬資源。

所以當前大部分的網(wǎng)絡應用都使用UTF-8編碼,因為網(wǎng)絡應用的代碼編寫全部都是使用的英文編寫,占據(jù)空間小,網(wǎng)絡傳輸速度快。

BOM編碼

比如一個文本軟件,在打開一個文件的時候,如何判斷這個文件是使用的什么編碼呢,該用什么編碼進行解碼呢?那么就需要通過BOM(Byte Order Mark)來指明了。

Unicode標準建議用BQM(Byte Order Mark)來區(qū)分字節(jié)序,即在傳輸字節(jié)流前,先傳輸被作為BOM的字符“零寬無中斷空格”。

這個字符的編碼是FEFF,而反過來的FFFE(UTF-16)FFFE0000(UTF-32)Unicode中都是未定義的碼位,不應該出現(xiàn)在實際傳輸中。

BOM主要用來指明編碼方式與大小端模式,比如新建一個文本文件,指定編碼格式

ANSI表示使用系統(tǒng)默認編碼我們如果選定一種格式進行保存

可以發(fā)現(xiàn),即使沒有內容,還是會有三個字節(jié)的大小,這就是因為有BOM來指定了文本文件的編碼方式。

想查看這些字節(jié)具體是什么,可以編寫程序(例如Java)用字節(jié)流讀取文本文件進行顯示

注意:UTF-8不需要BOM來表明字節(jié)順序,因為單個字節(jié)不涉及大小端的問題,但可以用BOM來表明文件是UTF-8的編碼方式。

根據(jù)BOM的規(guī)則,在一段字節(jié)流開始時,如果接收到以下字節(jié),則分別表明了該文本文件的編碼。

而如果不是以BOM開頭,那程序則會以ANSI,也就是系統(tǒng)默認編碼讀取。

亂碼原因

亂碼產(chǎn)生的根源一般情況下可以歸結為三方面即:

  • 編碼引起的亂碼
  • 解碼引起的亂碼
  • 缺少某種字體庫引起的亂碼(這種情況需要用戶安裝對應的字體庫)

其中大部分亂碼問題是由不合適的解碼方式造成的

亂碼可逆情況

其中缺少字體,只需要安裝對應的字體庫即可解決亂碼,比如Windows系統(tǒng)在C:\Windows\Fonts目錄下會有安裝好的字體庫列表。

安裝字體庫比較簡單,下載后解壓,然后復制到對應系統(tǒng)的Fonts目錄下。

解碼方式和編碼方式不一致的情況,只需要讓解碼方式和編碼方式一致即可讓亂碼恢復。

亂碼不可逆情況

總結補充

Unicode 有三種編碼方式,只有UTF-8兼容ASCII編碼,其他不兼容

資料鏈接:

https://www.bilibili.com/video/BV1HJ411E7d3?p=26

歡迎閱讀到這里,如果覺得文章有用,可以點擊下方的廣告鏈接,也算是對我的支持(當然,不強求哦)

本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
幫你搞清ASCII、Unicode和UTF-8區(qū)別,拿走不謝
字符串和編碼
Python:徹底搞懂Python的字符編碼
亂碼是怎么產(chǎn)生的?一“文”打盡亂碼問題
從編碼的縱橫歷史理解計算機編碼,以史鑒理
計算機編碼
更多類似文章 >>
生活服務
熱點新聞
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服