各种字符编码详解

作者:佘日茂

一、基础知识

1.字符集

什么是字符集?顾名思义,字符集就是字符的集合(这里的集合是数学意义上的集合)。比如汉字字符集,英文字符集等。

Unicode也是一种字符集,它包含了所有字符。

2.字符编码

字符编码是一套规则。是在字符与01比特串之间建立对应关系的一种规则。

U系列:UCS-2,UCS-4,UTF-8,UTF-16,UTF-32

中文系列:GB2312,GBK,gb18030,Big5

其他:ASCII,Latin-1,Shift_JIS,EUC-KR

3.特殊名词

ANSI不是一种编码方式。这是windows中使用的一个词,可以认为是一个地区的默认编码。在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在繁体中文Windows操作系统中,ANSI编码代表Big5编码;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码;在韩文Windows操作系统中,ANSI编码代表EUC-KR编码值。

附一则笑话:

话说计算机是由美国佬搞出来的嘛,他们觉得一个字节(可以表示256个编码)表示英语世界里所有的字母、数字和常用特殊符号已经绰绰有余了(其实ASCII只用了前127个编码)。后来欧洲人不干了,法国人说:我需要在小写字母加上变音符号(如:é),德国人说:我也要加几个字母(Ä ä、Ö ö、Ü ü、ß)。于是,欧洲人就将ASCII没用完的编码(128-255)为自己特有的符号编码(后来称之为“扩展字符集”)。等到我们中国人开始使用计算机的时候,尼玛,256个编码哪够?我泱泱大中华,汉字起码也得N多万吧,就连小学生都得要求掌握两三千字。

国标局最后拍板:一个字节不够,那我们就用多个字节来为汉字编码吧,但是,国情那么穷,字节那么贵,三个字节伤不起,那就用俩字节吧,先给常用的几千汉字编个码,等以后国家强盛了人民富裕了,咱再扩展呗---于是GB2312就产生了。

台湾同胞一看,尼玛,全是简体字,还让不让我们写繁体字的活了,于是台湾同胞也自己弄了个繁体字编码---大五码(Big-5)。同时,其它国家也在为自己的文字编码。最后,微软苦逼了:顾客就是上帝啊,你们的编码我都得满足啊,这样吧,卖给美国国内的系统默认就用ASCII编码吧,卖给中国人的系统默认就用GBK编码吧,卖给韩国人的系统默认就用EUC-KR编码,...但是为了避免你们误会我卖给你们的系统功能有差异,我就统一把你们的默认编码都显示成ANSI吧。---本故事纯属虚构,但“ANSI编码”确实只存在于Windows系统。(摘自:http://www.cnblogs.com/malecrab/p/5300486.html)

二、Unicode(UniversalMultiple-Octet Coded Character Set)

Unicode属于字符集,不属于编码,windows里的Unicode编码指的是UCS-2(下面会介绍)。

Unicode不仅是一种字符集,并且还为每个字符分配了一个数字,范围是0~0x10FFFF。所以,Unicode也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。

Unicode的文件头有两种:

大端模式为 0xFE 0xFF

小端模式为 0xFF 0xFE

三、常用编码

1.ASCII(American Standard Code for Information Interchange)

相信大家都知道吧?标准ASCII是128个,范围是0x00~0x7F。

2.UCS-4

四字节。这个简单粗暴的将Unicode中每个字符对应的数字存在四个字节里面。范围是0~0x7FFFFFFF,不过通常使用的范围是0~0x10FFFF。

3.UTF-32

四字节。UCS-4的子集,范围是0~0x10FFFF。

4.UCS-2

双字节。windows里的Unicode编码说的就是它了。它将Unicode中范围是0~0xFFFF的字符保存在两个字节中,其他字符没法编码保存。

5.UTF-16

双字节或四字节。

Unicode编码点分为17个平面(plane),每个平面包含65536个码位(code point),而第一个平面称为“基本多语言平面”(Basic Multilingual Plane,简称BMP),其余平面称为“辅助平面”(Supplementary Planes)。其中“基本多语言平面”(0~0xFFFF)中0xD800~0xDFFF之间的码位作为保留,未使用。UCS-2只能编码“基本多语言平面”中的字符,此时UTF-16与UCS-2的编码一样(都直接使用Unicode的码位作为编码值),例:“汉”在Unicode中的码位为6C49,而在UTF-16编码也为6C49。另外,UTF-16还可以利用保留下来的0xD800-0xDFFF区段的码位来对“辅助平面”的字符的码位进行编码,因此UTF-16可以为Unicode中所有的字符编码。

UTF-16中如何对“辅助平面”进行编码呢?

Unicode的码位区间为0~0x10FFFF,除“基本多语言平面”外,还剩0xFFFFF个码位(并且其值都大于或等于0x10000)。对于“辅助平面”内的字符来说,如果用它们在Unicode中码位值减去0x10000,则可以得到一个0~0xFFFFF的区间(该区间中的任意值都可以用一个20-bits的数字表示)。该数字的前10位(bits)加上0xD800,就得到UTF-16四字节编码中的前两个字节;该数字的后10位(bits)加上0xDC00,就得到UTF-16四字节编码中的后两个字节。例如:

(这个字念啥?^_^)

上面这个汉字的Unicode码位值为2AEAB,减去0x10000得到1AEAB(二进制值为0001 1010 1110 1010 1011),前10位加上D800得到D86B,后10位加上DC00得到DEAB。于是该字的UTF-16编码值为D86BDEAB(该值为大端表示,小端为6BD8ABDE)。

6.UTF-8(Unicode Transformation Format-8bit)

1~4字节。

允许含BOM,但通常不含BOM。UTF8的BOM头为 0xEF 0xBB 0xBF。UTF-8包含全世界所有国家需要用到的字符,是Unicode的实现方式之一。

unicode转utf-8方式:

第一种:Unicode从 0x0000 到 0x007F 范围的,是不是有点熟悉?对,其实就是标准ASCII码里面的内容,所以直接去掉前面那个字节 0x00,使用其第二个字节(与ASCII码相同)作为其编码,即为单字节UTF8。

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

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

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

7.GB系列

GB编码是中国创造的编码方式。包括GB2312、GBK、GB18030等,从字符集范围看,GB2312属于GBK属于GB18030。

GB2312:单字节(英文)或双字节(中文)。

GBK:单字节(英文)或双字节(中文)。

GB18030:单字节、双字节和4字节。

双字节2是全角的二,单字节即ASCII的2是半角的二。

高字节的最高位为0则为ASCII,为1则为中文。

GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。

GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。

2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。从汉字字汇上说,GB18030在GB13000.1的20902个汉字的基础上增加了CJK扩展A的6582个汉字(Unicode码0x3400-0x4db5),一共收录了27484个汉字。

GB2312简体中文编码表 http://www.knowsky.com/resource/gb2312tbl.htm

8.Big5

双字节,兼容ASCII。又称为大五码或五大码,是使用繁体中文(正体中文)社区中最常用的电脑汉字字符集标准,共收录13,060个汉字

9.Latin-1

又叫ISO-8859-1,单字节。可以认为是ASCII的扩展。

怎么区分不同的编码呢?有BOM头的,可以按照BOM头区分。没有BOM头的,只能按大量的编码分析来区分。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯移动品质中心TMQ的专栏

Python2中的中文字符编解码浅析

自动化测试过程中,输入文本、读取文件、解析网络请求、字符串断言、正则匹配这些步骤都是必不可少的。而Python是测试过程中最为常用的语言之一,很多测试团队的自动...

1966
来自专栏一名合格java开发的自我修养

字符编码笔记:ASCII,Unicode和UTF-8

很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物。他们看到8个开关状态是好的,于是他们把这称为"字节"。 再后来,...

651
来自专栏互扯程序

计算机编码 - 更易懂的打开方式

写在前面 对于计算机编码,记得当年上学学计算机时候肚子都被搞大了,不对,是脑袋被搞大了,后来勉强学会了吧,工作这么多年,真的是忘得一干二净,由于平时工作基本都...

2987
来自专栏数据处理

proc-tabulate-report

1064
来自专栏云飞学编程

python学习,数据分析系列工具,初识numpy

其实,数据分析看着很高大上,也很实用,但是真的很枯燥啊。。。。但是它又不得不学,毕竟数据分析对很多工作是很有帮助的,比如爬虫,抓到的数据,不论是保存到文件还是数...

492
来自专栏C语言及其他语言

[程序源码]C语言实现简单计算器(VC6.0环境)

程序源码 ? 今天给大家带来一个C语言实现简单计算器(VC6.0环境)的程序源码,好了,咱们话不多说,直接上源码—— #include <stdio.h...

5667
来自专栏个人分享

MapReduce编程job概念原理

  在Hadoop中,每个MapReduce任务都被初始化为一个job,每个job又可分为两个阶段:map阶段和reduce阶段。这两个阶段分别用两个函数来表示...

631
来自专栏Python小屋

Python内置函数int()高级用法

int()函数常用来把其他类型转换为整数,例如: >>> int(3.2) 3 >>> int(1/3) 0 其实,int是Python内置类型之一,之所以能...

2837
来自专栏玄魂工作室

如何学Python 第十八课 位运算符介绍

欢迎回来! 在我们上一次的培训课程中,我们介绍了类以及OOP如何使编程/脚本更容易。 今天我们将休息一下,并且介绍一些相当简单的按位运算符。 按位运算符相对简单...

3015
来自专栏desperate633

一个故事带你搞懂ASCII,Unicode字符集和UTF-8编码

快下班时,爱问问题的小朋友Nico又问了一个问题: "sqlserver里面有char和nchar,那个n据说是指unicode的数据,这个是什么意思。" ...

742

扫码关注云+社区