ANSI,ASCII,Unicode,UTF-8的區別。自認為寫得最好的一篇
文章推薦指數: 80 %
ANSI,ASCII,Unicode,utf-8的區別與聯絡. 很久很久以前,有一群人,他們決定用8個可以開合的電晶體來組合成不同的狀態,以表示世界上的萬物。
程式人生>>ANSI,ASCII,Unicode,UTF-8的區別。
自認為寫得最好的一篇
ANSI,ASCII,Unicode,UTF-8的區別。
自認為寫得最好的一篇
阿新••發佈:2019-02-13
原帖地址:http://www.myexception.cn/other/1464250.html
ANSI,ASCII,Unicode,utf-8的區別與聯絡
很久很久以前,有一群人,他們決定用8個可以開合的電晶體來組合成不同的狀態,以表示世界上的萬物。
他們看到8個開關狀態是好的,於是他們把這稱為"位元組"。
再後來,他們又做了一些可以處理這些位元組的機器,機器開動了,可以用位元組來組合出很多狀態,狀態開始變來變去。
他們看到這樣是好的,於是它們就這機器稱為"計算機"。
開始計算機只在美國用。
八位的位元組一共可以組合出256(2的8次方)種不同的狀態。
他們把其中的編號從0開始的32種狀態分別規定了特殊的用途,一但終端、印表機遇上約定好的這些位元組被傳過來時,就要做一些約定的動作。
遇上00x10,終端就換行,遇上0x07,終端就向人們嘟嘟叫,例好遇上0x1b,印表機就列印反白的字,或者終端就用彩色顯示字母。
他們看到這樣很好,於是就把這些0x20以下的位元組狀態稱為"控制碼"。
他們又把所有的空格、標點符號、數字、大小寫字母分別用連續的位元組狀態表示,一直編到了第127號,這樣計算機就可以用不同位元組來儲存英語的文字了。
大家看到這樣,都感覺很好,於是大家都把這個方案叫做ANSI的"Ascii"編碼(AmericanStandardCodeforInformationInterchange,美國資訊互換標準程式碼)。
當時世界上所有的計算機都用同樣的ASCII方案來儲存英文文字。
後來,就像建造巴比倫塔一樣,世界各地的都開始使用計算機,但是很多國家用的不是英文,他們的字母裡有許多是ASCII裡沒有的,為了可以在計算機儲存他們的文字,他們決定採用127號之後的空位來表示這些新的字母、符號,還加入了很多畫表格時需要用下到的橫線、豎線、交叉等形狀,一直把序號編到了最後一個狀態255。
從128到255這一頁的字符集被稱"擴充套件字符集"。
從此之後,貪婪的人類再沒有新的狀態可以用了,美帝國主義可能沒有想到還有第三世界國家的人們也希望可以用到計算機吧!
等中國人們得到計算機時,已經沒有可以利用的位元組狀態來表示漢字,況且有6000多個常用漢字需要儲存呢。
但是這難不倒智慧的中國人民,我們不客氣地把那些127號之後的奇異符號們直接取消掉,規定:一個小於127的字元的意義與原來相同,但兩個大於127的字元連在一起時,就表示一個漢字,前面的一個位元組(他稱之為高位元組)從0xA1用到0xF7,後面一個位元組(低位元組)從0xA1到0xFE,這樣我們就可以組合出大約7000多個簡體漢字了。
在這些編碼裡,我們還把數學符號、羅馬希臘的字母、日文的假名們都編進去了,連在ASCII
裡本來就有的數字、標點、字母都統統重新編了兩個位元組長的編碼,這就是常說的"全形"字元,而原來在127號以下的那些就叫"半形"字元了。
中國人民看到這樣很不錯,於是就把這種漢字方案叫做"GB2312"。
GB2312是對ASCII的中文擴充套件。
但是中國的漢字太多了,我們很快就就發現有許多人的人名沒有辦法在這裡打出來,特別是某些很會麻煩別人的國家領導人。
於是我們不得不繼續把GB2312沒有用到的碼位找出來老實不客氣地用上。
後來還是不夠用,於是乾脆不再要求低位元組一定是127號之後的內碼,只要第一個位元組是大於127就固定表示這是一個漢字的開始,不管後面跟的是不是擴充套件字元集裡的內容。
結果擴充套件之後的編碼方案被稱為GBK標準,GBK包括了GB2312的所有內容,同時又增加了近20000個新的漢字(包括繁體字)和符號。
後來少數民族也要用電腦了,於是我們再擴充套件,又加了幾千個新的少數民族的字,GBK擴成了GB18030。
從此之後,中華民族的文化就可以在計算機時代中傳承了。
中國的程式設計師們看到這一系列漢字編碼的標準是好的,於是通稱他們叫做"DBCS"(DoubleByteCharecterSet雙位元組字符集)。
在DBCS系列標準裡,最大的特點是兩位元組長的漢字字元和一位元組長的英文字元並存於同一套編碼方案裡,因此他們寫的程式為了支援中文處理,必須要注意字串裡的每一個位元組的值,如果這個值是大於127的,那麼就認為一個雙位元組字符集裡的字元出現了。
那時候凡是受過加持,會程式設計的計算機僧侶們都要每天念下面這個咒語數百遍:
"一個漢字算兩個英文字元!一個漢字算兩個英文字元……"
因為當時各個國家都像中國這樣搞出一套自己的編碼標準,結果互相之間誰也不懂誰的編碼,誰也不支援別人的編碼,連大陸和臺灣這樣只相隔了150海里,使用著同一種語言的兄弟地區,也分別採用了不同的DBCS編碼方案——當時的中國人想讓電腦顯示漢字,就必須裝上一個"漢字系統",專門用來處理漢字的顯示、輸入的問題,但是那個臺灣的愚昧封建人士寫的算命程式就必須加裝另一套支援BIG5編碼的什麼"倚天漢字系統"才可以用,裝錯了字元系統,顯示就會亂了套!這怎麼辦?而且世界民族之林中還有那些一時用不上電腦的窮苦人民,他們的文字又怎
麼辦?
真是計算機的巴比倫塔命題啊!
正在這時,大天使加百列及時出現了——一個叫ISO(國際標誰化組織)的國際組織決定著手解決這個問題。
他們採用的方法很簡單:廢了所有的地區性編碼方案,重新搞一個包括了地球上所有文化、所有字母和符號的編碼!他們打算叫它"UniversalMultiple-OctetCodedCharacterSet",簡稱UCS,俗稱"UNICODE"。
UNICODE開始制訂時,計算機的儲存器容量極大地發展了,空間再也不成為問題了。
於是ISO就直接規定必須用兩個位元組,也就是16位來統一表示所有的字元,對於ascii裡的那些“半形”字元,UNICODE包持其原編碼不變,只是將其長度由原來的8位擴充套件為16位,而其他文化和語言的字元則全部重新統一編碼。
由於"半形"英文符號只需要用到低8位,所以其高8位永遠是0,因此這種大氣的方案在儲存英文文字時會多浪費一倍的空間。
這時候,從舊社會裡走過來的程式設計師開始發現一個奇怪的現象:他們的strlen函式靠不住了,一個漢字不再是相當於兩個字元了,而是一個!是的,從UNICODE開始,無論是半形的英文字母,還是全形的漢字,它們都是統一的"一個字元"!同時,也都是統一的"兩個位元組",請注意"字元"和"位元組"兩個術語的不同,“位元組”是一個8位的物理存貯單元,而“字元”則是一個文化相關的符號。
在UNICODE中,一個字元就是兩個位元組。
一個漢字算兩個英文字元的時代已經快過去了。
從前多種字符集存在時,那些做多語言軟體的公司遇上過很大麻煩,他們為了在不同的國家銷售同一套軟體,就不得不在區域化軟體時也加持那個雙位元組字符集咒語,不僅要處處小心不要搞錯,還要把軟體中的文字在不同的字符集中轉來轉去。
UNICODE對於他們來說是一個很好的一攬子解決方案,於是從WindowsNT開始,MS趁機把它們的作業系統改了一遍,把所有的核心程式碼都改成了用UNICODE方式工作的版本,從這時開始,WINDOWS系統終於無需要加裝各種本土語言系統,就可以顯示全世界上所有文化的字元了。
但是,UNICODE在制訂時沒有考慮與任何一種現有的編碼方案保持相容,這使得GBK與UNICODE在漢字的內碼編排上完全是不一樣的,沒有一種簡單的算術方法可以把文字內容從UNICODE編碼和另一種編碼進行轉換,這種轉換必須通過查表來進行。
如前所述,UNICODE是用兩個位元組來表示為一個字元,他總共可以組合出65535不同的字元,這大概已經可以覆蓋世界上所有文化的符號。
如果還不夠也沒有關係,ISO已經準備了UCS-4方案,說簡單了就是四個位元組來表示一個字元,這樣我們就可以組合出21億個不同的字元出來(最高位有其他用途),這大概可以用到銀河聯邦成立那一天吧!
UNICODE來到時,一起到來的還有計算機網路的興起,UNICODE如何在網路上傳輸也是一個必須考慮的問題,於是面向傳輸的眾多UTF(UCSTransferFormat)標準出現了,顧名思義,UTF8就是每次8個位傳輸資料,而UTF16就是每次16個位,只不過為了傳輸時的可靠性,從UNICODE到UTF時並不是直接的對應,而是要過一些演算法和規則來轉換。
受到過網路程式設計加持的計算機僧侶們都知道,在網路裡傳遞資訊時有一個很重要的問題,就是對於資料高低位的解讀方式,一些計算機是採用低位先發送的方法,例如我們PC機採用的INTEL架構,而另一些是採用高位先發送的方式,在網路中交換資料時,為了核對雙方對於高低位的認識是否是一致的,採用了一種很簡便的方法,就是在文字流的開始時向對方傳送一個標誌符——如果之後的文字是高位在位,那就傳送"FEFF",反之,則傳送"FFFE"。
不信你可以用二進位制方式開啟一個UTF-X格式的檔案,看看開頭兩個位元組是不是這兩個位元組?
講到這裡,我們再順便說說一個很著名的奇怪現象:當你在windows的記事本里新建一個檔案,輸入"聯通"兩個字之後,儲存,關閉,然後再次開啟,你會發現這兩個字已經消失了,代之的是幾個亂碼!呵呵,有人說這就是聯通之所以拼不過移動的原因。
其實這是因為GB2312編碼與UTF8編碼產生了編碼衝撞的原因。
從網上引來一段從UNICODE到UTF8的轉換規則:
Unicode
UTF-8
0000-007F
0xxxxxxx
0080-07FF
110xxxxx10xxxxxx
0800-FFFF
1110xxxx10xxxxxx10xxxxxx
例如"漢"字的Unicode編碼是6C49。
6C49在0800-FFFF之間,所以要用3位元組模板:1110xxxx10xxxxxx10xxxxxx。
將6C49寫成二進位制是:0110110001001001,將這個位元流按三位元組模板的分段方法分為0110110001001001,依次代替模板中的x,得到:1110-011010-11000110-001001,即E6B189,這就是其UTF8的編碼。
而當你新建一個文字檔案時,記事本的編碼預設是ANSI,如果你在ANSI的編碼輸入漢字,那麼他實際就是GB系列的編碼方式,在這種編碼下,"聯通"的內碼是:
c111000001
aa10101010
cd11001101
a810101000
注意到了嗎?第一二個位元組、第三四個位元組的起始部分的都是"110"和"10",正好與UTF8規則裡的兩位元組模板是一致的,於是再次開啟記事本時,記事本就誤認為這是一個UTF8編碼的檔案,讓我們把第一個位元組的110和第二個位元組的10去掉,我們就得到了"00001101010",再把各位對齊,補上前導的0,就得到了"0000000001101010",不好意思,這是UNICODE的006A,也就是小寫的字母"j",而之後的兩位元組用UTF8解碼之後是0368,這個字元什麼也不是。
這就是隻有"聯通"兩個字的檔案沒有辦法在記事本里正常顯示的原因。
而如果你在"聯通"之後多輸入幾個字,其他的字的編碼不見得又恰好是110和10開始的位元組,這樣再次開啟時,記事本就不會堅持這是一個utf8編碼的檔案,而會用ANSI的方式解讀之,這時亂碼又不出現了。
好了,終於可以回答NICO的問題了,在資料庫裡,有n字首的字串型別就是UNICODE型別,這種型別中,固定用兩個位元組來表示一個字元,無論這個字元是漢字還是英文字母,或是別的什麼。
如果你要測試"abc漢字"這個串的長度,在沒有n字首的資料型別裡,這個字串是7個字元的長度,因為一個漢字相當於兩個字元。
而在有n字首的資料型別裡,同樣的測試串長度的函式將會告訴你是5個字元,因為一個漢字就是一個字元。
1.ASCII碼
我們知道,在計算機內部,所有的資訊最終都表示為一個二進位制的字串。
每一個二進位制位(bit)有0和1兩種狀態,因此八個二進位制位就可以組合出256種狀態,這被稱為一個位元組(byte)。
也就是說,一個位元組一共可以用來表示256種不同的狀態,每一個狀態對應一個符號,就是256個符號,從0000000到11111111。
上個世紀60年代,美國製定了一套字元編碼,對英語字元與二進位制位之間的關係,做了統一規定。
這被稱為ASCII碼,一直沿用至今。
ASCII
碼一共規定了128個字元的編碼,比如空格“SPACE”是32(二進位制00100000),大寫的字母A是65(二進位制01000001)。
這128個符號(包括32個不能打印出來的控制號)只佔用了一個位元組的後面7位,最前面的1位統一規定為0。
2、非ASCII編碼
英語用128個符號編碼就夠了,但是用來表示其他語言,128個符號是不夠的。
比如,在法語中,字母上方有注音符號,它就無法用ASCII碼錶示。
於是,一些歐洲國家就決定,利用位元組中閒置的最高位編入新的符號。
比如,法語中的é的編碼為130(二進位制10000010)。
這樣一來,這些歐洲國家使用的編碼體系,可以表示最多256個符號。
但是,這裡又出現了新的問題。
不同的國家有不同的字母,因此,哪怕它們都使用256個符號的編碼方式,代表的字母卻不一樣。
比如,130在法語編碼中代表了é
,在希伯來語編碼中卻代表了字母Gimel(),在俄語編碼中又會代表另一個符號。
但是不管怎樣,所有這些編碼方式中,0—127表示的符號是一樣的,不一樣的只是128
—255的這一段。
至於亞洲國家的文字,使用的符號就更多了,漢字就多達10萬左右。
一個位元組只能表示256種符號,肯定是不夠的,就必須使用多個位元組表達一個符號。
比如,簡體中文常見的編碼方式是GB2312,使用兩個位元組表示一個漢字,所以理論上最多可以表示256x256=65536個符號。
中文編碼的問題需專文討論,這篇筆記不涉及。
這裡只指出,雖然都是用多個位元組表示一個符號,但是GB類的漢字編碼與後文的Unicode和UTF-8是毫無關係的。
3.Unicode
正如上一節所說,世界上存在著多種編碼方式,同一個二進位制數字可以被解釋成不同的符號。
因此,要想開啟一個文字檔案,就必須知道它的編碼方式,否則用錯誤的編碼方式解讀,就會出現亂碼。
為什麼電子郵件常常出現亂碼?就是因為發信人和收信人使用的編碼方式不一樣。
可以想象,如果有一種編碼,將世界上所有的符號都納入其中。
每一個符號都給予一個獨一無二的編碼,那麼亂碼問題就會消失。
這就是Unicode,就像它的名字都表示的,這是一種所有符號的編碼。
Unicode當然是一個很大的集合,現在的規模可以容納100多萬個符號。
每個符號的編碼都不一樣,比如,U+0639表示阿拉伯字母Ain,U+0041表示英語的大寫字母A,U+4E25表示漢字“嚴”。
具體的符號對應表,可以查詢unicode.org,或者專門的漢字對應表。
4.Unicode
的問題需要注意的是,Unicode只是一個符號集,它只規定了符號的二進位制程式碼,卻沒有規定這個二進位制程式碼應該如何儲存。
比如,漢字“嚴”的unicode是十六進位制數4E25,轉換成二進位制數足足有15位(100111000100101),也就是說這個符號的表示至少需要2個位元組。
表示其他更大的符號,可能需要3個位元組或者4個位元組,甚至更多。
這裡就有兩個嚴重的問題,第一個問題是,如何才能區別unicode和ascii?計算機怎麼知道三個位元組表示一個符號,而不是分別表示三個符號呢?第二個問題是,我們已經知道,英文字母只用一個位元組表示就夠了,如果unicode統一規定,每個符號用三個或四個位元組表示,那麼每個英文字母前都必然有二到三個位元組是0,這對於儲存來說是極大的浪費,文字檔案的大小會因此大出二三倍,這是無法接受的。
它們造成的結果是:1)出現了unicode的多種儲存方式,也就是說有許多種不同的二進位制格式,可以用來表示unicode。
2)
unicode在很長一段時間內無法推廣,直到網際網路的出現。
5.UTF-8
網際網路的普及,強烈要求出現一種統一的編碼方式。
UTF-8就是在網際網路上使用最廣的一種unicode的實現方式。
其他實現方式還包括UTF-16和UTF-32,不過在網際網路上基本不用。
重複一遍,這裡的關係是,UTF-8是Unicode的實現方式之一。
UTF-8最大的一個特點,就是它是一種變長的編碼方式。
它可以使用1~4個位元組表示一個符號,根據不同的符號而變化位元組長度。
UTF-8的編碼規則很簡單,只有二條:
1)對於單位元組的符號,位元組的第一位設為0,後面7位為這個符號的unicode碼。
因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
2)對於n位元組的符號(n>1),第一個位元組的前n位都設為1,第n+1位設為0,後面位元組的前兩位一律設為10。
剩下的沒有提及的二進位制位,全部為這個符號的unicode碼。
下表總結了編碼規則,字母x表示可用編碼的位。
下面,還是以漢字“嚴”為例,演示如何實現UTF-8編碼。
已知“嚴”的unicode是4E25(100111000100101),根據上表,可以發現4E25處在第三行的範圍內(00000800-0000FFFF),因此“嚴”的UTF-8編碼需要三個位元組,即格式是“1110xxxx10xxxxxx10xxxxxx”。
然後,從“嚴”的最後一個二進位制位開始,依次從後向前填入格式中的x,多出的位補0。
這樣就得到了,“嚴”的UTF-8編碼是“111001001011100010100101”,轉換成十六進位制就是E4B8A5。
OpenCV3.3出爐,DNN為最大亮點
«上一篇
分析一下B2B網站運營的幾點要求下一篇»
相關推薦
ANSI,ASCII,Unicode,UTF-8的區別。
自認為寫得最好的一篇
原帖地址:http://www.myexception.cn/other/1464250.html
ANSI,ASCII,...
字元編碼:ANSI和ASCII區別、Unicode和UTF-8區別
ANSI和ASCII區別
ANSI碼(Americ...
字元編碼ANSI和ASCII區別、Unicode和UTF-8區別
今天看了一個說法,說是入坑windows程式開發,必先掌握文字的編碼和字符集知識。
本部落格就整理下資訊儲存和字元...
字符編碼ANSI和ASCII區別、Unicode和UTF-8區別
span編輯日本發展不同語言保存code導致styleANSI碼ANSI編碼是一種對ASCII碼的拓展:A...
常見三種字元編碼的區別:ASCII、Unicode、UTF-8
什麼是字元編碼?
計算機只能處理數字,如果要處理文字,就必須先把文字轉換為數字才能處理。
最早的計算機在設計時採...
弄懂進位制、bit、java基本資料型別(byte、short、int、char、String)、ASCII、Unicode、UTF-8、UTF-16的關聯關係及UTF-8、UTF-16編碼原理
首先普及一下基本概念:
1.數值(百度百科):指的是用數目表示的一個量的多少;
2.進位制(百度百科):也就是進位計數制,是人為定義的帶進位的...
UNICODE,GBK,UTF-8區別
一、編碼歷史與區別
一直對字元的各種編碼方式懵懵懂懂,什麼A...
ASCII,Unicode,UTF-8,UTF-16,ANSI字元編碼比較
標準ASCII,其最高位(b7)用作奇偶校驗位。
擴充套件ASCII字元是從128到255(0x80-0xff)的字元。
擴...
關於字符編碼,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)
tlecatihttpchar表示編寫編號小端調用字符編碼的問題看似很小,經常被技術人員忽視,但是很容易導...
編碼歷史ASCII、Unicode、utf-8和GBK
英文字母英文全世界兩個編碼中國歷史1的個數包含ASCII編碼:用來表示所有的大寫和小寫字母,數字0到9、...
搜尋
基礎教學
Mysql入門
Sql入門
Android入門
Docker入門
Go語言入門
Ruby程式入門
Python入門
Python進階
Django入門
Python爬蟲入門
最近訪問
ANSI,ASCII,Unicode,UTF-8的區別。
自認為寫得最好的一篇
Spring+Boot+2+入手
VirtualBox+ubuntu-16.04.2+下NAT+Host-only網絡配置
GStreamer流媒體知識介紹
CSS布局(四)+左右布局
彩票的倒計時和期數
JQuery使用load方法載入外部div時,css,js無效的辦法
C語言中static的作用及C語言中使用靜態函式有何好處
jquery的empty()和remove()方法
glib學習筆記之三——GLib核心應用支援:glib+中+IO+Channels+理解
延伸文章資訊
- 1Unicode 與UTF-8 的差別 - Mobile01
我們常說的unicode編碼指的是utf-16, utf-8 是通用的html/xml編碼, 對ascii字元, utf-8用單字元編碼, utf-16用2字元, 超出utf-8的256字元外的...
- 2ANSI,ASCII,Unicode,UTF-8的區別。自認為寫得最好的一篇
ANSI,ASCII,Unicode,utf-8的區別與聯絡. 很久很久以前,有一群人,他們決定用8個可以開合的電晶體來組合成不同的狀態,以表示世界上的萬物。
- 3「底層原理」Unicode與UTF-8的區別 - 每日頭條
UTF-8是一種變長的編碼方式。它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。UTF-8的編碼規則有 ...
- 4Unicode 和UTF-8 有什么区别? - 知乎
举一个例子:It's 知乎日报. 你看到的unicode字符集是这样的编码表:. I 0049 t 0074 ' 0027 s 0073 0020 知77e5 乎4e4e 日65e5 报62a5...
- 5Unicode、UTF-8、UTF-16,終於懂了 - 閱坊