字符集

ASCII,区位码,GB2312,GBK,Unicode,UTF8
在这里插入图片描述

1.ASCII

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语,而其扩展版本EASCII则可以勉强显示其他西欧语言。它是现今最通用的单字节编码系统(但是有被Unicode追上的迹象),并等同于国际标准ISO/IEC 646。

ASCII字符集:主要包括控制字符(回车键、退格、换行键等);可显示字符(英文大小写字符、阿拉伯数字和西文符号)。

ASCII编码:将ASCII字符集转换为计算机可以接受的数字系统的数的规则。使用7位(bits)表示一个字符,共128字符;但是7位编码的字符集只能支持128个字符,为了表示更多的欧洲常用字符对ASCII进行了扩展,ASCII扩展字符集使用8位(bits)表示一个字符,共256字符。ASCII字符集映射到数字编码规则如下图所示:
图1 ASCII编码表
图2 扩展ASCII编码表

2.区位码与GB2312、GBK

区位码是早些年(1980)中国制定的一个编码标准,4个数字表示一个字符。请看下面的区位码表,每一个字符都有对应一个编号。其中前两位为“区”,后两位为“位”,中文汉字的编号区号是从16开始的,位号从1开始。前面的区号有一些符号、数字、字母、注音符号(台)、制表符、日文等等。
在这里插入图片描述
而GB2312编码就是基于区位码的,用双字节编码表示中文和中文符号。一般编码方式是:0xA0+区号,0xA0+位号。如下表中的 “安”,区位号是1618(十进制),那么“安”字的GB2312编码就是 0xA0+16 0xA0+18 也就是 0xB0 0xB2 。根据区位码表,GB2312的汉字编码范围是0xB0A1~0xF7FE
可能大家注意到了,区位码里有英文和数字,按道理说是不是也应该是双字节的呢。而一般情况下,我们见到的英文和数字是单字节的,以ASCII编码,也就是说现代的GBK编码是兼容ASCII编码的。比如一个数字2,对应的二进制是0x32,而不是 0xA3 0xB2。那么问题来了,0xA3 0xB2 又对应到什么呢?还是2(笑)。注意看了,这里的2跟2是不是有点不太一样?!确实是不一样的。这里的双字节2是全角的二,ASCII的2是半角的二,一般输入法里的切换全角半角就是这里不同。

如果留意过早些年的手机(功能机),会发现人名中常见的“燊”字是打不出来的。为什么呢?因为早期的区位码表里面并没有这些字,也就是说早期的GB2312也是没有这些字的。到后来的GBK(1995)才补充了大量的汉字进去,当然现在的安卓苹果应该都是GBK字库了。再看看这些补充的汉字的字节码 燊 0x9F 0xF6 。和前面说到的GB2312不同,有的字的编码比 0xA0 0xA0 还小,难道新补充的区位号还能是负的??其实不然,这次的补充只补充了计算机编码表,并没有补充区位码表。也就是说区位码表并没有更新,用区位码打字法还是打不出这些字,而网上的反向区位码表查询也只是按照GBK的编码计算,并不代表字与区位号完全对应。时代的发展,区位码表早已经是进入博物馆的东西了。

Big5是与GB2312同时期的一种台湾地区繁体字的编码格式。后来GBK编码的制定,把Big5用的繁体字也包含进来(但编码不兼容),还增加了一些其它的中文字符。细心的朋友可能还会发现,台湾香港用的繁体字(如KTV里的字幕)跟大陆用的繁体字还有点笔画上的不一样,其实这跟编码无关,是字体的不同,大陆一般用的是宋体楷体黑体,港澳台常用的是明体(鸟哥Linux私房菜用的是新細明體)。GBK总体编码范围为0x8140~0xFEFE,首字节在 0x81~0xFE 之间,尾字节在 0x40~0xFE 之间,剔除 xx7F 一条线。详细编码表可以参考这个列表。微软Windows安排给GBK的code page(代码页)是CP936,所以有时候看到编码格式是CP936,其实就是GBK的意思。2000年和2005年,国家又先后两次发布了GB18030编码标准,兼容GBK,新增四字节的编码,但比较少见

GB码,全称是GB2312-80《信息交换用汉字编码字符集 基本集》,1980年发布,是中文信息处理的国家标准,在大陆及海外使用简体中文的地区(如新加坡等)是强制使用的唯一中文编码。P-Windows3.2和苹果OS就是以GB2312为基本汉字编码, Windows 95/98则以GBK为基本汉字编码、但兼容支持GB2312。GB码共收录6763个简体汉字、682个符号,其中汉字部分:一级字3755,以拼音排序,二级字3008,以偏旁排序。该标准的制定和应用为规范、推动中文信息化进程起了很大作用。
GBK: 汉字国标扩展码,基本上采用了原来GB2312-80所有的汉字及码位,并涵盖了原Unicode中所有的汉字20902,总共收录了883个符e69da5e6ba907a686964616f31333234326434号, 21003个汉字及提供了1894个造字码位。 Microsoft简体版中文Windows 95就是以GBK为内码,又由于GBK同时也涵盖了Unicode所有CJK汉字,所以也可以和Unicode做一一对应。
GBK编码是中国大陆制订的、等同于UCS的新的中文编码扩展国家标准。GBK工作小组于1995年10月,同年12月完成GBK规范。该编码标准兼容GB2312,共收录汉字21003个、符号883个,并提供1894个造字码位,简、繁体字融于一库。

3.UTF8编码 与 Unicode编码

GBK是中国标准,只在中国使用,并没有表示大多数其它国家的编码;而各国又陆续推出各自的编码标准,互不兼容,非常不利于全球化发展。于是后来国际组织发行了一个全球统一编码表,把全球各国文字都统一在一个编码标准里,名为Unicode。很多人都很疑惑,到底UTF8与Unicode两者有什么关系?如果要类比的话,UTF8相当于GB2312,Unicode相当于区位码表,不同的是它们之间的编号范围和转换公式。那什么是原始的Unicode编码呢?如果你用过PHP的话,json_encode函数默认会把中文编码成为Unicode,比如“首发于博客园”就会转码成“\u9996\u53d1\u4e8e\u535a\u5ba2\u56ed”。可以看到每个字都变成了 \uXXXX 的形式,这个就是文字的对应Unicode编码,\u表示Unicode的意思,网上也有用U+表示unicode。现行的Unicode编码标准里,绝大多数程序语言只支持双字节。英文字母、标点也收纳在Unicode编码中。有兴趣的可以在站长工具里尝试“中文转Unicode”,可以得到你输入文字的Unicode编码。

因为英文字符也全部使用双字节,存储成本和流量会大大地增加,所以Unicode编码大多数情况并没有被原始地使用,而是被转换编码成UTF8。下表就是其转换公式:
在这里插入图片描述
第一种:Unicode从 0x0000 到 0x007F 范围的,是不是有点熟悉?对,其实就是标准ASCII码里面的内容,所以直接去掉前面那个字节 0x00,使用其第二个字节(与ASCII码相同)作为其编码,即为单字节UTF8。

第二种:Unicode从 0x0080 到 0x07FF 范围的,转换成双字节UTF8。

第三种:Unicode从 0x8000 到 0xFFFF 范围的,转换成三字节UTF8,一般中文都是在这个范围里。

第四种:超过双字节的Unicode目前还没有广泛支持,仅见emoji表情在此范围。

例如“博”字的Unicode编码是\u535a。0x535A在0x0800~0xFFFF之间,所以用3字节模板 1110yyyy 10yyyyxx 10xxxxxx。将535A写成二进制是:0101 0011 0101 1010,高八位分别代替y,低八位分别代替x,得到 11100101 10001101 10011010,也就是 0xE58D9A ,这就是博字的UTF8编码。

前面提到,GBK的编码里英文字符有全角和半角之分,全角为GBK的标准编码过的双字节2,半角为ASCII的单字节2。那现在UTF8是全部用一个公式,理论上只有半角的2的,怎么支持全角的2呢?哈哈,结果是Unicode为中国特色的全角英文字符也单独分配了编码,简单粗暴。比如全角的2的Unicode编码是 \uFF12,转换到UTF8就是 0xEFBC92。
优点
UTF-8是ASCII的一个超集。因为一个纯ASCII字符串也是一个合法的UTF-8字符串,所以现存的ASCII文本不需要转换。为传统的扩展ASCII字符集设计的软件通常可以不经修改或很少修改就能与UTF-8一起使用。
使用标准的面向字节的排序例程对UTF-8排序将产生与基于Unicode代码点排序相同的结果。(尽管这只有有限的有用性,因为在任何特定语言或文化下都不太可能有仍可接受的文字排列顺序。)
UTF-8和UTF-16都是可扩展标记语言文档的标准编码。所有其它编码都必须通过显式或文本声明来指定。
任何面向字节的字符串搜索算法都可以用于UTF-8的数据(只要输入仅由完整的UTF-8字符组成)。但是,对于包含字符记数的正则表达式或其它结构必须小心。
UTF-8字符串可以由一个简单的算法可靠地识别出来。就是,一个字符串在任何其它编码中表现为合法的UTF-8的可能性很低,并随字符串长度增长而减小。举例说,字符值C0,C1,F5至FF从来没有出现。为了更好的可靠性,可以使用正则表达式来统计非法过长和替代值(可以查看W3 FAQ: Multilingual Forms上的验证UTF-8字符串的正则表达式)。
缺点
因为每个字符使用不同数量的字节编码,所以寻找串中第N个字符是一个O(N)复杂度的操作 — 即,串越长,则需要更多的时间来定位特定的字符。同时,还需要位变换来把字符编码成字节,把字节解码成字符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值