各种字符编码详解

作者:佘日茂

一、基础知识

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 条评论
登录 后参与评论

相关文章

来自专栏开发与安全

数据结构:栈的链式存储结构

当单链表限定只能在头部进行插入和删除操作的时候,即为链栈,一般我们会将单链表的头指针和栈的栈顶指针top合二为一,通常对链栈来说,是不需要头节点的,因为我们维护...

1898
来自专栏SeanCheney的专栏

《Pandas Cookbook》第06章 索引对齐1. 检查索引2. 求笛卡尔积3. 索引爆炸4. 用不等索引填充数值5. 从不同的DataFrame追加列6. 高亮每列的最大值7. 用链式方法重现

第01章 Pandas基础 第02章 DataFrame运算 第03章 数据分析入门 第04章 选取数据子集 第05章 布尔索引 第06章 索引对齐 ...

401
来自专栏青玉伏案

算法导论之最大子段和

  《算法导论》一书中对最大字段和可谓讲的是栩栩如生,楚楚动人。如果简单的说最大字段和,没有意义。而《算法导论》上举了一个股票的例子。根据股票每天结束的价格来求...

2027
来自专栏Albert陈凯

2018-08-23 Java工具类——全角半角字符相互转换

https://blog.csdn.net/xyw591238/article/details/51719747 https://my.oschina.net...

621
来自专栏ACM算法日常

当七夕遇上算法竞赛

  七夕节因牛郎织女的传说而被扣上了「情人节」的帽子。于是TYVJ今年举办了一次线下七夕祭。Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去T...

672
来自专栏开发与安全

数据结构:两栈共享存储空间

数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈为栈的末端,即下标为数组长度 n-1处。这样,如果两个栈增加元素,就是两端点...

2415
来自专栏智能计算时代

Analyze tweets in under 30 minutes using Node-RED

I created a Node-RED app in Bluemix which searches for a specified keyword, user...

2756
来自专栏Java成神之路

Java_util_02_Java判断字符串是中文还是英文

做微信开发,使用百度翻译API时,需要指定译文的语种。这就需要我们判断待翻译内容是中文还是英文,若是中文,则翻译成英文,若是英文则翻译成中文。

695
来自专栏数据结构与算法

P1095 守望者的逃离

题目描述 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变。守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上。为了杀死守望者,...

2536
来自专栏数据结构与算法

BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)

541

扫码关注云+社区