tft每日頭條

 > 生活

 > unicode編碼和ascii碼一樣嗎

unicode編碼和ascii碼一樣嗎

生活 更新时间:2024-07-29 18:07:45

unicode編碼和ascii碼一樣嗎(計算機編碼ASCIIGBKUnicode)1

在計算機中,所有的數據在存儲和運算時都要使用二進制數值表示(因為計算機用高電平和低電平分别表示1和0),而具體用哪些二進制數字表示哪個符号,當然每個人都可以約定自己的一套(這就叫編碼),而大家如果要想互相通信而不造成混亂,那麼大家就必須使用相同的編碼規則,這就是統一編碼的原因。簡單來說編碼就是字符與數值的對應關系。下面我們詳細介紹不同編碼的編碼規則和應用。

ASCII編碼

ASCII碼是由美國有關的标準化組織出台的,後來它被國際标準化組織(International Organization for Standardization, ISO)定為國際标準,稱為ISO 646标準。該标準統一規定了常用字符(像a、b、c、d這樣的52個字母(包括大寫)以及0、1等數字還有一些常用的符号(例如:%、!、 等)總共128個字符)如何用二進制數來表示。ASCII分為标準ASCII 碼使用7 位二進制數組合來表示128種字符和擴展ASCII的8 位二進制數組合來表示256種字符。

  • 标準ASCII

0-127所包含的碼稱為标準ASCII編碼,如:空格SPACE是32(二進制00100000),大寫的字母a是97(二進制01100001)。這128個符号(包括32個不能打印出來的控制符号),隻占用了一個字節(8位)的後7位,最前面的一位統一規定為0。

下面是标準ASCII碼表:

unicode編碼和ascii碼一樣嗎(計算機編碼ASCIIGBKUnicode)2

  • 擴展ASCII碼

後128個稱為擴展ASCII碼。擴展ASCII碼允許将每個字符的第8 位用于确定附加的128 個特殊符号字符、外來語字母和圖形符号;

下面是擴展ASCII碼表:

unicode編碼和ascii碼一樣嗎(計算機編碼ASCIIGBKUnicode)3

在python中可以使用内置函數ord()查看單個字符的ASCII碼,例如:

>>> ord('a') 97

ord() 函數實質是返回字符的 Unicode 碼對應的十進制數值。例如

>>> ord("國") 22269

另外,ord()逆函數chr()查看編碼對應的字符,例如:

>>> chr(97) 'a' >>> chr(22269) '國'

gbk

由于ASCII編碼是不支持中文的,但又需要尋求一種編碼方式來支持中文。于是,國人就定義了一套編碼規則:當字符小于127位時,與ASCII的字符相同,但當兩個大于127的字符連接在一起時,就代表一個漢字,第一個字節稱為高字節(從0xA1-0xF7),第二個字節為低字節(從0xA1-0xFE),這樣大約可以組合7000多個簡體漢字。這個規則叫做GB2312。

由于中國漢字很多,有些字還是無法表示,于是重新定義了規則:不在要求低字節一定是127之後的編碼,隻要第一個字節是大于127,就固定表示這是一個漢字的開始,不管後面跟的是不是擴展字符集裡的内容。這種擴展之後的編碼方案稱之為GBK,包含了GB2312的所有内容,同時新增了近20000個新的漢字(包括繁體字)和符号。但是,中國有56個民族,每個民族都有自己的文字,所以,對GBK編碼規則進行了擴展,又加了近幾千個少數民族的字符,再次擴展後得編碼叫做GB18030,GBK字符是被包含在GB18030字符内的,與GBK基本向後兼容。 GB18030共收錄漢字70,244個.

Python中使用gbk和gb18030編碼'韓'字:

>>> "韓".encode("gb18030") b'\xba\xab' >>> "韓".encode("gbk") b'\xba\xab'

ANSI:

為使計算機支持更多的語言,通常使用 0x80~0xFFFF 範圍内的2個字節來表示1個字符。比如:漢字 '中' 在中文操作系統中,使用0xD6、0xD0這兩個字節存儲。但不同的國家和地區制定了不同的标準,由此産生了 GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的編碼标準。這些使用多個字節來代表一個字符的各種延伸編碼方式,被稱為 ANSI 編碼。在簡體中文Windows操作系統為中,ANSI 編碼代表 GBK 編碼在繁體中文Windows操作系統中,ANSI編碼代表Big5;而在日文Windows操作系統中,ANSI 編碼代表 Shift_JIS 編碼。不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法将屬于兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。ANSI編碼表示英文字符時用一個字節,表示中文用兩個或四個字節。

Unicode

因為世界上有很多國家,而每個國家都定義一套自己的編碼标準,結果相互之間無法解析編碼進行通信,所以ISO(國際标準化組織)決定定義一套編碼方案來解決所有國家的編碼問題,這個新的編碼方案就叫做Unicode。注意Unicode不是一個新的編碼規則,而是一套字符集(為每一個「字符」分配一個唯一的 ID(學名為碼位 / 碼點 / Code Point)),可以将Unicode理解為一本世界編碼的字典。具體的符号對應表,可以查詢,或者專門的漢字對應表。

在Python中查看字符對應Unicode數值的方法:

>>> "中".encode("unicode_escape") b'\\u4e2d' >>> b'\\u4e2d'.decode("unicode_escape") '中'

需要注意的是,Unicode 隻是一個符号集,它隻規定了符号的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。比如,漢字嚴的 Unicode 是十六進制數4E25,轉換成二進制數足足有15位(1001110 00100101),也就是說,這個符号的表示至少需要2個字節。表示其他更大的符号,可能需要3個字節或者4個字節,甚至更多。這裡就有幾個嚴重的問題,第一個問題是,計算機如何才能區别 Unicode 和 ASCII ?還有計算機怎麼知道三個字節表示一個符号,而不是分别表示三個符号呢?第二個問題是,我們已經知道,英文字母隻用一個字節表示就夠了,如果 Unicode 統一規定,每個符号用三個或四個字節表示,那麼每個英文字母前都必然有二到三個字節是0,這對于存儲或傳輸來說是極大的浪費,文本文件的大小會因此大出二三倍,這是無法接受的。它們造成的結果是:出現了 Unicode 的多種存儲方式,也就是說有許多種不同的二進制格式,可以用來表示 Unicode。也導緻了Unicode 在很長一段時間内無法推廣,直到UTF編碼的出現。

utf-8編碼

由于Unicode比較浪費網絡和硬盤資源,因此為了解決這個問題,就在Unicode的基礎上,定制了一套編碼規則(将「碼位」轉換為字節序列的規則【編碼/解碼 可以理解為 加密/解密 的過程】),這個新的編碼規則就是UTF-8。UTF-8采用1-4個字符進行傳輸和存儲數據,是一種針對Unicode的可變長度字符編碼,又稱萬國碼。

Unicode與Utf-8編碼規則:使用下面的模闆進行互轉

Unicode符号範圍(十六進制) | UTF-8編碼方式(二進制)

------------------------------------------------------------------------

0000 0000-0000 007F | 0xxxxxxx

0000 0080-0000 07FF | 110xxxxx 10xxxxxx

0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx

0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Unicode字符通過對應模闆加上标志位就後是Utf-8編。例如:"迷" Unicode的編碼為 \\u8ff7 用二進制表示為:‭10001111 11110111‬,8ff7處于第三個模闆範圍内,把10001111 11110111 按模闆分成三份 1000 111111 110111,然後加上标志位的二進制為:11101000 10111111 10110111 所以utf-8編碼是"‭E8BFB7‬"

Python中Unicode字符轉UTF-8編碼:

>>>'迷'.encode('utf-8') b'\xe8\xbf\xb7'

那麼如何區分utf-8各個字符的?utf-8區分每個字符的開始是根據編碼的高位字節來區分的,比如:用一個字節表示的字符,第一個字節高位以"0"開頭;用兩個字節表示的字符,第一個字節的高位為以"110"開頭,後面一個字節以"10開頭";用三個字節表示的字符,第一個字節以"1110"開頭,後面兩個字節以"10"開頭;用四個字節表示的字符,第一個字節以"11110"開頭,後面的三個字節以"10"開頭。這樣計算機就可以認出每個字符由幾個字節組成,才能顯示出正确的信息。

UTF-8和Unicode轉換

比如漢字"智",utf-8編碼是"\xe6\x99\xba"對應的二進制為:"11100110 10011001 10111010",由于utf-8中一個漢字是3個字節,所以對應的模闆為:

0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx

11100110 10011001 10111010 | UTF-8編碼成的二進制1110xxxx 10xxxxxx 10xxxxxx | 對應模版 0110 011001 111010 |去除模版中的标志位後01100110 01111010代表十六進制667A,因此根據規則轉換得出"智"Unicode的編碼為667A。

同樣,根據Unicode中字符的編碼位置,也能找到對應的utf-8編碼。例如:UTF-8編碼:\xe8\xbf\xb7,用二進制表示為:‭11101000 10111111 10110111‬,有3個字節屬于第三個模闆範圍,按模闆去掉标志位後是:1000 111111 110111,結果就是'迷'字的Unicode字符 8ff7

>>> b'\\u8ff7'.decode('unicode_escape') '迷'

Unicode與GBK編碼的轉換

Unicode 與 GBK 是兩個完全不同的字符編碼方案, 其兩者沒有直接關系。如果要對其進行相

互轉換, 最直接最高效的方法是查詢各自的字符對照表。

Python實現Unicode與GBK轉換(将Unicode對應數值:\\u8ff7轉GBK字符方法):

>>> l_u = b'\\u8ff7'.decode('unicode_escape') >>> l_u.encode('gbk') b'\xc3\xd4'

UTF-8、Unicode與GBK的關系

Utf-8(utf-16)====編碼====Unicode=====編碼=====GBK(ANSI)

Utf-8(utf-16)====解碼====Unicode===解碼=======GBK(ANSI)

總結:Unicode字符可以通過編碼可以得到UTF-8和GBK,相反UTF-8和GBK也可以通過解碼得到Unicode,但GBK和UTF-8之間無法直接轉換,隻能轉換到Unicode後再轉到另一編碼。其實所謂編碼轉換是數值與字符的轉換。

URL編碼 /解碼

URL編碼就是一個字符ascii碼的十六進制。不過稍微有些變動,需要在前面加上"%"。比如"\",它的ascii碼是92,92的十六進制是5c,所以"\"的URL編碼就是\。那麼漢字的URL編碼呢?很簡單,非ASCII字符的編碼一般有兩種,是以GBK或UTF8進行編碼。例如:"迷" 對應的UTF-8編碼\xe8\xbf\xb7,則"胡"的URL編碼是迷。解碼方法是去掉%,之後再進行UTF-8解碼,就可以得到實際的字符了。

計算機是以什麼編碼存儲和傳輸數據的呢?

支持Unicode的應用程序(python、VS、VC、Google Chrome、notepad等大多數程序都支持(部分程序需要設置編碼)。

不支持Unicode的應用程序(易語言等)則會以控制面闆—區域—管理中設置的編碼(ANSI)進行存儲,例如:簡體中文(GBK)、繁體中文(Big5)等。

例如:以國産編程語言‘易語言’為例,看一下變量在内存中是以什麼編碼存儲的

a = "你" 調試輸出 (取指針地址_文本型 (a)) * 1966420

通過CE查看此内存地址中對應的值為0000E3C4,而"你"的GBK編碼正好為:E3C4。由此得知,易語言軟件是以GBK編碼進行數據存儲和傳輸的。

再看看數據在内存中如何存儲:

· 使用OD查看

unicode編碼和ascii碼一樣嗎(計算機編碼ASCIIGBKUnicode)4

· 使用CE查看

unicode編碼和ascii碼一樣嗎(計算機編碼ASCIIGBKUnicode)5

多字符變量"你好啊"的GBK字符:c4e3bac3b0a1

OD:

unicode編碼和ascii碼一樣嗎(計算機編碼ASCIIGBKUnicode)6

CE(8字節顯示):

unicode編碼和ascii碼一樣嗎(計算機編碼ASCIIGBKUnicode)7

由此可以看出,内存的存儲編碼方式與軟件支持的編碼方式是一緻的(易語言:GBK字符;python:Unicode字符);計算機内存數據存儲一般采用大端模式(内存高位對數據低位,内存低位對數據高位) 。OD默認是從内存低位到高位顯示數據,CE默認是從内存高位到低位顯示數據,所以看到的十六進制數值是相反的。存儲占用的内存大小,會根據變量的數據類型申請對應大小的内存來存儲。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved