gbk编码是什么意思(gbk和utf8的区别)
在计算机中,所有的数据在存储和运算时都要使用二进制数值表示(因为计算机用高电平和低电平分别表示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码表:
- 扩展ascii码
后128个称为扩展ascii码。扩展ascii码允许将每个字符的第8 位用于确定附加的128 个特殊符号字符、外来语字母和图形符号;
下面是扩展ascii码表:
在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'xbaxab' >>> "韩".encode("gbk") b'xbaxab'
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'xe8xbfxb7'
那么如何区分utf-8各个字符的?utf-8区分每个字符的开始是根据编码的高位字节来区分的,比如:用一个字节表示的字符,第一个字节高位以”0″开头;用两个字节表示的字符,第一个字节的高位为以”110″开头,后面一个字节以”10开头”;用三个字节表示的字符,第一个字节以”1110″开头,后面两个字节以”10″开头;用四个字节表示的字符,第一个字节以”11110″开头,后面的三个字节以”10″开头。这样计算机就可以认出每个字符由几个字节组成,才能显示出正确的信息。
utf-8和unicode转换
比如汉字”智”,utf-8编码是”xe6x99xba”对应的二进制为:”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编码:xe8xbfxb7,用二进制表示为: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'xc3xd4'
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编码就是%5c。那么汉字的url编码呢?很简单,非ascii字符的编码一般有两种,是以gbk或utf8进行编码。例如:”迷” 对应的utf-8编码xe8xbfxb7,则”胡”的url编码是%e8%bf%b7。解码方法是去掉%,之后再进行utf-8解码,就可以得到实际的字符了。
计算机是以什么编码存储和传输数据的呢?
支持unicode的应用程序(python、vs、vc、google chrome、notepad等大多数程序都支持(部分程序需要设置编码)。
不支持unicode的应用程序(易语言等)则会以控制面板—区域—管理中设置的编码(ansi)进行存储,例如:简体中文(gbk)、繁体中文(big5)等。
例如:以国产编程语言‘易语言’为例,看一下变量在内存中是以什么编码存储的
a = "你" 调试输出 (取指针地址_文本型 (a)) * 1966420
通过ce查看此内存地址中对应的值为0000e3c4,而”你”的gbk编码正好为:e3c4。由此得知,易语言软件是以gbk编码进行数据存储和传输的。
再看看数据在内存中如何存储:
· 使用od查看
· 使用ce查看
多字符变量”你好啊”的gbk字符:c4e3bac3b0a1
od:
ce(8字节显示):
由此可以看出,内存的存储编码方式与软件支持的编码方式是一致的(易语言:gbk字符;python:unicode字符);计算机内存数据存储一般采用大端模式(内存高位对数据低位,内存低位对数据高位) 。od默认是从内存低位到高位显示数据,ce默认是从内存高位到低位显示数据,所以看到的十六进制数值是相反的。存储占用的内存大小,会根据变量的数据类型申请对应大小的内存来存储。
推荐阅读
-
gbk编码是什么意思(gbk和utf8的区别)
-
gbk编码是什么意思(gbk和utf8的区别)
-
go语言 进行文件编码格式转换中(GBK 转UTF8),可能出错部分文件出现乱码情况的解决。
-
utf8和unicode编码究竟是什么关系?有何区别?
-
PHP数组编码gbk与utf8互相转换的两种方法
-
php截取字符串之截取utf8或gbk编码的中英文字符串示例_php实例
-
php截取字符串之截取utf8或gbk编码的中英文字符串示例
-
PHP遍历中文目录的gbk编码和utf-8编码之间如何转换
-
gbk编码的数据导入到utf8编码的数据库_MySQL
-
php导入到Excel 的 utf8、gbk 编码_PHP教程