漫話:如何給女友解釋什麼是"錕斤拷"?

漫話:如何給女友解釋什麼是"錕斤拷"?

週末女友出去逛街了,我本身一我的在家看綜藝節目,忽然,女友給我打來電話。html

過了一會,女友回來了,她拿出手機,給我看了她在超市拍的照片:編程

微信

要想知道什麼是亂碼,須要先從計算機編碼提及。編程語言

字符編碼和ASCII網站

咱們常常看一些諜戰劇,諜戰劇裏敵特、地下黨員以及八路軍各部間發送情報的時候,通常都是經過電報發送的,電報在傳遞的過程當中,須要發報員用電鍵發出長短不一的電碼,收報員就會聽到電報機發出的滴滴滴答答答的聲音。其實電報發出的聲音都是"滴"和"答"的組合,"答"的聲音是"滴"的三倍長。搜索引擎

發報員要先經過一種方式,將想要發送的情報轉成電報的滴答聲,收報員在聽到滴答聲以後,再將它們翻譯成正常的文字。這個過程就是字符編碼和字符解碼。編碼

諜戰劇中將情報轉成電報的"滴"和"答"聲主要經過摩爾斯電碼,這是一種經過不一樣的排列順序來表達不一樣的英文字母、數字和標點符號的字符編碼方式。莫爾斯電碼由短的和長的電脈衝(稱爲點和劃)所組成。點和劃的時間長度都有規定,以一點爲一個基本單位,一劃等於三個點的長度。正好對應上電報的"滴"和"答"。spa

就像電報只能發出"滴"和"答"聲同樣,計算機只認識0和1兩種字符,可是,人類的文字是多種多樣的,如何把人類的文字轉換成計算機認識的01字符呢,這個過程一樣須要經過字符編碼。操作系統

字符編碼(Character encoding)是一套法則,使用該法則可以對天然語言的字符的一個集合(如字母表或音節表),與其餘東西的一個集合(如號碼或電脈衝)進行配對。翻譯

和摩爾斯電碼功能相似,上個世紀60年代,美國製定了一套字符編碼,對英語字符與二進制位之間的關係,作了統一規定,這被稱爲 ASCII 碼,一直沿用至今。

**ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼)是基於拉丁字母的一套計算機編碼系統。它主要用於顯示現代英語,其中共有128個字符,包含了全部的大寫和小寫字母,數字0到九、標點符號, 以及在美式英語中使用的特殊控制字符等。

因爲ASCII只有128個字符,雖然對於英文字符均可以表示了,可是世界上還有不少其餘的文字他是沒辦法表示的,因此須要一種更加全面的字符編碼。

在介紹其餘的字符編碼以前,咱們先來講一下一個計算機領域通用的字符集。

Unicode

Unicode(中文:萬國碼、國際碼、統一碼、單一碼)是計算機科學領域裏的一項業界標準。它對世界上大部分的文字系統進行了整理、編碼,使得計算機能夠用更爲簡單的方式來呈現和處理文字。

Unicode至今仍在不斷增修,每一個新版本都加入更多新的字符。目前最新的版本爲2019年5月公佈的12.1,這一版本只新增了一個字符,即日本新年號令和的合字。

Unicode備受承認,並普遍地應用於計算機軟件的國際化與本地化過程。有不少新科技,如可擴展置標語言(Extensible Markup Language,簡稱:XML)、Java編程語言以及現代的操做系統,都採用Unicode編碼。

Unicode是一套通用的字符集,包含世界上的大部分文字,也就是說,Unicode是能夠表示中文的。

UTF-8 UTF-16 UTF-32

Unicode雖然統一了全世界字符的編碼,但沒有規定如何存儲。這麼作是有考慮的:

若是Unicode統一規定,每一個符號就要用三個或四個字節表示,由於字符太多,只能用這麼多字節才能表示徹底。

一旦這麼規定,那麼每一個英文字母前都必然有二到三個字節是0,由於全部英文字母在ASCII中都有,均可以用一個字節表示,剩餘字節位置就要補充0。

若是這樣,文本文件的大小會所以大出二三倍,這對於存儲來講是極大的浪費。爲了解決這個問題,就出現了一些中間格式的字符集,他們被稱爲通用轉換格式,即UTF(Unicode Transformation Format)。常見的UTF格式有:UTF-7, UTF-7.5, UTF-8,UTF-16, 以及 UTF-32。

UTF-8 使用一至四個字節爲每一個字符編碼

UTF-16 使用二或四個字節爲每一個字符編碼

UTF-32 使用四個字節爲每一個字符編碼

因此咱們能夠說,UTF-八、UTF-16等都是 Unicode 的一種實現方式。

舉個例子,Unicode規定了一箇中文字符 "我"對應的unicode是"\u6211",可是,在UTF-8和UTF-16等不一樣的實現方式下,這個二進制code的存儲方式是不同的。

UTF-8使用可變長度字節來儲存 Unicode字符,例如ASCII字母繼續使用1字節儲存,重音文字、希臘字母或西裏爾字母等使用2字節來儲存,而經常使用的漢字就要使用3字節。輔助平面字符則使用4字節。

GBK,GB2312,GB18030

由於UTF-8是Unicode的一種實現,因此他包含了世界上的全部文字的編碼,他採用的是1-4字節進行編碼。

對於那些排在前面優先歸入的文字,可能就優先使用1字節、2字節存儲了,對於後歸入的文字,就要使用3字節或者4字節存儲了。

正是由於他太全了,因此那些晚一些歸入的字符,在UTF-8中的存儲所佔的字節數可能就會多一些,那他的存儲空間要求就會很大。

對於經常使用的漢字,在UTF-8中採用3字節進行編碼,可是若是有一種只包含中文和ASCII的編碼的話,就不須要使用3個字節,可能2個字節就夠了。

對於大部分網站來講,基本都是隻服務一個國家或者地區的,好比一箇中國的網站,通常會出現簡體字和繁體字以及一些英文字符,不多會出現日語或者韓文的。

也是出於這樣的考慮,中國國家標準總局於1981年制定並實施了 GB 2312-80 編碼,即中華人民共和國國家標準簡體中文字符集。後來廠商微軟利用GB 2312-80未使用的編碼空間,收錄GB 13000.1-93所有字符制定了GBK編碼。

有了標準中文字符集,若是是一個純中文網站,就能夠能夠採用這種編碼方式,這樣能夠大大節省一些存儲空間的。

經常使用的中文編碼有GBK,GB2312,GB18030等,最經常使用的是GBK。

  • GB2312(1980年):16位字符集,收錄有6763個簡體漢字,682個符號,共7445個字符;

  • 優勢:適用於簡體中文環境,屬於中國國家標準,通行於大陸,新加坡等地也使用此編碼;

  • 缺點:不兼容繁體中文,其漢字集合過少。

  • GBK(1995年):16位字符集,收錄有21003個漢字,883個符號,共21886個字符;

  • 優勢:適用於簡繁中文共存的環境,爲簡體Windows所使用,向下徹底兼容gb2312,向上支持 ISO-10646 國際標準 ;全部字符均可以一對一映射到unicode2.0上;

  • 缺點:不屬於官方標準,和big5之間須要轉換;不少搜索引擎都不能很好地支持GBK漢字。

  • GB18030(2000年):32位字符集;收錄了27484個漢字,同時收錄了藏文、蒙文、維吾爾文等主要的少數民族文字。

  • 優勢:能夠收錄全部你能想到的文字和符號,屬於中國最新的國家標準;

  • 缺點:目前支持它的軟件較少。

亂碼

咱們還拿前面介紹過的發電報的例子來講,假設有如下場景:

發報員使用"美式摩爾斯電碼"將情報轉換成電報,收報員接收到電報以後,經過"現代國際摩爾斯電碼"進行破譯。那麼獲得的情報內容就可能徹底看不懂,這就是亂碼了。

就像在計算機領域,咱們把一串中文字符經過UTF-8進行編碼傳輸給別人,別人拿到這串文字以後,經過GBK進行解碼,獲得的內容就會是「錕屆瀿錕斤拷雮傡錕斤拷直錕斤拷錕」,這就是亂碼。

如如下代碼:

public static void main(String[] args) throws UnsupportedEncodingException {
    String s = "漫話編程!";

    byte[] bytes = s.getBytes(Charset.forName("GBK"));

    System.out.println("GBK編碼,GBK解碼:" + new String(bytes, "GBK"));

    System.out.println("GBK編碼,GB18030解碼:" + new String(bytes, "GB18030"));

    System.out.println("GBK編碼,UTF-8解碼:" + new String(bytes, "UTF-8"));
}
複製代碼

輸出結果:

GBK編碼,GBK解碼:漫話編程!
GBK編碼,GB18030解碼:漫話編程!
GBK編碼,UTF-8解碼:????????
複製代碼

能夠看到,將中文字符,經過GBK編碼,再使用UTF-8解碼,獲得的字符就是一串問號,這就是亂碼了。

錕斤拷的前世此生

由於Unicode是一直在更新的,在這個過程當中,確定有一些比較新的字符他是沒法表示的。或者即便Unicode發佈了新版歸入了某個文字,可是不少軟件系統並未升級也會有這樣的問題。

就像生活中一些手機廠商新出的那些emoji表情,在本身的手機上能夠正常顯示,發到其餘品牌的手機上可能就沒法顯示。這其實也是字符集不支持致使的。

發生以上狀況時,沒法顯示的時候也須要有一個字符來表示的,在Unicode中,這個字符就是 � ,他也是Unicode中定義的一個特殊字符。也就是"0xFFFD REPLACEMENT CHARACTER",全部沒法表示的字符都會經過這個字符來表示。

Unicode官方有關於這個符號的介紹,從上表中能夠看到,他的10進製表示是65533,在UTF-8下,他的16進制形式是'0xEF 0xBF 0xBD'(三個字節)。

若是有兩個連續的字符都沒法顯示,如"� �" ,那麼在UTF-8編碼下,16進製表示爲:

0xEF 0xBF 0xBD 
0xEF 0xBF 0xBD
複製代碼

以上這段編碼,若是放到GBK中進行解碼的話,由於GBK中一個漢字兩個字節,那麼結果就是:

0xEF 0xBF, 0xBD 0xEF, 0xBF 0xBD
複製代碼

0xEFBF
0xBDEF
0xBFBD
複製代碼

那麼,若是展現出來,就是:錕(0xEFBF),斤(0xBDEF),拷(0xBFBD),因此,之後再見到錕斤拷,第一時間想到UTF-8和GBK的轉換問題準沒錯。

除了錕斤拷之外,還有兩組比較經典的亂碼,分別是"燙燙燙"和"屯屯屯",這兩個亂碼產生自VC,這是debug模式下VC對內存的初始化操做。VC會把棧中新分配的內存初始化爲0xcc,而把堆中新分配的內存初始化爲0xcd。把0xcc和0xcd按照字符打印出來,就是燙和屯了。

加入戰隊

# <span id="addMe">加入戰隊</span>

微信公衆號

微信公衆號

原文出處:https://www.cnblogs.com/zhangxinhua/p/11444677.html

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息