突然想搞清楚各种字符编码

你有没有想过,为什么你发给别人的文件会变成乱码?使用Windows记事本的“另存为”,会看到一个Encoding的字段,它有什么意义呢?

忽然想搞清楚各种字符编码。

1. 基本概念

Encoding意思是“编码”,与其对应的是Decoding,即“解码”。计算机为什么要进行“编码”和“解码”呢?

我们知道,计算机以二进制形式来传输数据,每一个二进制位(bit)有0和1两种状态。无论从键盘输入,还是读取一个文件,计算机处理的内容其实都是一堆二进制序列。计算机想要读取一些内容,进行处理,然后重新显示到屏幕上,就必须按照某种特定的规则进行编码和解码。例如,把字符'A'存入计算机时,计算机会用"01100001"二进制字符串来表示和处理该字符;读取时,再将"01100001"还原成字符'A'

字符集(Charset):系统支持的所有字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。

字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符集(如字母表或音节表),与其他东西的集合(如号码或电脉冲)进行配对。通常人们用自然语言来表达信,而以计算机为基础的信息处理系统则是利用元件(硬件)不同状态的组合来存储和处理信息的。简单来说,编码、解码就是在做翻译工作。将人类理解的自然语言翻译成为计算机理解的二进制数的过程称为“编码(Encoding)”;将这些二进制数重新转化为自然语言的过程称为“解码(Decoding)”,解码,是编码的逆过程。

2. 常见字符集与编码

常见字符集包含:ASCII、GB2312、BIG5、GB18030、Unicode等。每一种字符集都有对应的编码标准。

2.1 ASCII码

在计算机中,所有数据在传输、存储和处理时,都用二进制数来表示,这是因为计算机分别用高电平和低电平表示1和0。我们将一个二进制位称为一个bit,每个bit有 0 和 1 两种状态。8个二进制位(bit)被称为一个字节byte)。因此,一个字节可以用来表示 28 = 256 种不同的状态,每一个状态对应一个符号,就是256个符号,从0000000011111111

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是美国制定的基于拉丁字母的一套电脑编码系统,主要用于显示英语和其他西欧语言。它是现今最通用的单字节编码系统。ASCII 码使用指定的7位或8位二进制数组合来表示 27 = 128 或 28 = 256 种可能的字符。

2.1.1 标准ASCII码

标准ASCII码也叫基础ASCII码,标准ASCII码字符集主要包括:

  • 控制字符(回车键、退格、换行键等)

  • 英文大小写字符

  • 阿拉伯数字

标准ASCII字符编码只占用一个字节的后7位,最前面一位统一规定为0。用来表示所有的大小写字母,数字0到9、标点符号,以及控制字符。其中:

  • 0 ~ 31 及 127 是控制字符或通信专用字符。如:LF(换行)、CR(回车)、BS(退格)等

  • 32是空格

  • 48 ~ 57 为0到9十个阿拉伯数字

  • 65 ~ 90 为26个大写英文字母

  • 97 ~ 122 为26个小写英文字母

  • 其余为一些标点符号、运算符号等

ASCII码排序:数字的ASCII码 < 大写字母的ASCII码 < 小写字母的ASCII码。

2.1.2 扩展ASCII码

英语用128个符号编码就够了,但是其他语言,128个符号远远不够。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号,这样就可以表示最多256个符号。扩展ASCII码就是从128 到 255(0x80-0xff)的字符。扩展ASCII码允许将每个字符的第8 位用于确定附加的128 个特殊符号字符、外来语字母和图形符号。

针对扩展的ASCII码,不同的国家有不同的字符集,所以它并不是国际标准。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。

2.2 GBXXXX

计算机发明后很长一段时间,只用应用于一些西方发达国家,ASCII就能够满足需要。但当计算机在中国兴起之后,必须设计一套编码规则来对汉字进行编码。

2.2.1 GB2312

GB2312 或 GB2312–80 是简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,又称GB0,由中国国家标准总局发布,1981年5月1日实施。GB2312编码通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB2312。

GB2312字符集共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。

把扩展ASCII码中127号之后的符号去掉,GB2312字符编码规则如下:

  • 小于127的字符的意义与标准ASCII码相同,称为半角字符

  • 两个大于127的字符连在一起时,就表示一个汉字,前一个字节(高字节)从0xA1到 0xF7,后一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,还把数学符号、罗马希腊的 字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的全角字符

GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。但对于人名、古汉语等方面出现的罕用字和繁体字,GB2312仍然不能处理,因此后来GBK及GB18030汉字字符集相继出现以解决这些问题。

2.2.2 GBK

GBK(Chinese Internal Code Specification),汉字内码扩展规范。GBK 共收入 21886 个汉字和图形符号,其中包括GB2312 中的全部汉字、非汉字符号。

GBK 采用双字节表示,总体编码范围为 8140-FEFE 之间,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 XX7F 一条线。GBK 编码区分三部分:

① 汉字区 包括: 

  • GBK/2:OXBOA1-F7FE, 收录 GB 2312 汉字 6763 个,按原序排列

  • GBK/3:OX8140-AOFE,收录 CJK 汉字 6080 个

  • GBK/4:OXAA40-FEAO,收录 CJK 汉字和增补的汉字8160个

② 图形符号区 包括: 

  • GBK/1:OXA1A1-A9FE,除 GB 2312 的符号外,还增补了其它符号

  • GBK/5:OXA840-A9AO,扩除非汉字区

③ 用户自定义区 

  • GBK 区域中的空白区,用户可以自己定义字符

2.2.3 GB 18030

GBK只为“技术规范指导性文件”,不属于国家标准。国家质量技术监督局于2000年3月17日推出了GB 18030-2000标准,以取代GBK。GB 18030-2000除保留全部GBK编码汉字,在第二字节把能使用范围再度进行扩展,增加了大约一百个汉字及四位元组编码空间,但是将GBK作为子集全部保留。

GB18030主要有以下特点:

  • 采用变长多字节编码,每个字可以由1个、2个或4个字节组成

  • 编码空间庞大,最多可定义161万个字符

  • 支持中国国内少数民族文字,不需要动用造字区

  • 汉字收录范围包含繁体汉字以及日韩汉字

GB18030算得上是一种Unicode的变换格式(UTF),但和UTF-8相比要复杂得多。GB18030包含三种长度的编码:单字节的ASCII、双字节的GBK(略带扩展)、以及用于填补所有Unicode码位的四字节UTF区段。

2.3 Unicode

要想打开一个文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么你发给别人的文件会变成乱码?就是因为发送者和接收者的编码方式不一样。

ASCII码的问题在于,尽管在0-127号字符的使用上达成了一致,但对于128-255号字符,各个语言却对其有不同的解释。汉字等亚洲语言就更糟心了,一个字节不够用,开始使用两个字节来存储。

那么问题来了,到底有没有一种编码标准,囊括世界上所有语言的字符集?如果每一个符号都给予一个独一无二的编码,那么乱码问题就会得到彻底的解决。没错,Unicode标准字符集诞生了。

Unicode(统一码、万国码、单一码、标准万国码)是业界的一种标准,基于通用字符集(Universal Character Set)的标准来发展。到目前为止,Unicode 就已经包含了超过十万个字符。

目前的Unicode字符分为17组编排,0x0000 至 0x10FFFF,每组称为平面(Plane),而每平面拥有216 = 65536 个码位,共1114112个。然而目前只用了少数平面。

基本多文种平面(Basic Multilingual Plane, BMP),或称第0平面或0号平面(Plane 0),是Unicode中的一个最常用的编码区段。编码从U+0000至U+FFFF。以下是Unicode基本多文种平面的示意图。每个写着数字的格子代表256个码点。

UCS-2是指用两个字节对应一个字符的字符集;UCS-4则是指用四个字节对应一个字符的字符集。我们可以认为,目前为止Unicode有两个具体的字符集:UCS-2和UCS-4。 

Unicode 只是一个庞大的、全球通用的字符集,每个字符在Unicode字符集中都能找到唯一确定的编号(字符码,又称Unicode码),但在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,Unicode的实现方式有所不同。Unicode的实现方式称为Unicode转换格式(Unicode Transformation Format,简称为UTF)。

UTF包括UTF-7、UTF-8、UTF-16和UTF-32,后面的数字代表转换时最小的位数,比如,UTF-8就是用几个8位二进制数来代表一个Unicode编码。当下两个最流行的Unicode实现是UTF-8 和 UTF-16。

2.3.1 UTF-8

如果每个字符都使用2字节的原Unicode编码传输,其第一字节的8位始终为0。这就造成了比较大的浪费。对于这种情况,可以使用UTF-8编码。

UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,以 8 bit为一个编码单位,使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。UTF-8是在互联网上使用最广的一种Unicode的实现方式。

UTF-8 的编码规则:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。

2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

下表总结了编码规则,字母x表示可用编码的位。跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

2.3.2 UTF-16

尽管有Unicode字符非常多,但是实际上大多数人不会用到超过前65535个以外的字符。因此,就有了另外一种Unicode编码方式,叫做UTF-16(因为16位 = 2字节)。UTF-16将0–65535范围内的字符编码成2个字节。其编码方法是:

  • 如果字符编码U小于0x10000,也就是十进制的0到65535之内,则直接使用两字节表示;

  • 如果字符编码U大于0x10000,由于UNICODE编码范围最大为0x10FFFF,从0x10000到0x10FFFF之间 共有0xFFFFF个编码,也就是需要20个bit就可以标示这些编码。用U'表示从0-0xFFFFF之间的值,将其前 10 bit作为高位和16 bit的数值0xD800进行 逻辑or 操作,将后10 bit作为低位和0xDC00做 逻辑or 操作,这样组成的 4个byte就构成了U的编码。

3. HTTP中的字符编码

在HTTP中,与字符集和字符编码相关的消息头包含:Accept-Charset Accept-Encoding Accept-LanguageContent-Type Content-Encoding Content-Language

  • Accept-Charset:浏览器申明自己接收的字符集,如:gb2312,utf-8。通常我们说Charset包括了相应的字符编码方案

  • Accept-Encoding:浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法,如:gzip,deflate

  • Accept-Language:浏览器申明自己接收的语言。语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等

  • Content-Type:WEB服务器告诉浏览器自己响应的对象的类型和字符集。例如:Content-Type: text/html; charset=‘gb2312’

  • Content-Encoding:WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。例如:Content-Encoding:gzip

  • Content-Language:WEB服务器告诉浏览器自己响应的对象的语言。


参考资料:
1. 字符编码笔记:ASCII,Unicode 和 UTF-8
2. 维基百科. 字符编码, 2011-1-5
3. 维基百科. ASCII, 2011-4-5
4. 维基百科. GB2312, 2011-3-17
5. 维基百科. GB18030, 2010-3-10
6. 维基百科. GBK, 2011-3-7
7. 维基百科. Unicode, 2011-4-30

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值