参考文档:

http://baike.baidu.com/view/443268.htm?fromId=25492

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

http://tech.idv2.com/2008/02/21/unicode-intro/

http://baike.baidu.com/view/185282.htm

http://baike.baidu.com/view/40801.htm

http://hilojack.sinaapp.com/?p=1291

个人学到的先附加在如下:

ASCII

1. ASCII码只表示128个字符,最前面一位为0. ASCII是计算机的一个基础存储格式。其他存储格式也都为它做了预留。

Unicode与UCS2\UTF8\UTF16

1. Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。UCS-2用两个字节编码,UCS-4用4个字节编码。

我们通常Windows上见到的Unicode,不做说明的情况下,都是指的UCS-2这种字节编码。

2. Unicode UCS2使用两个字节来存储,是我们大多数情况都用到的uniocde方式,代码中使用也很方便(w_char)-双字节与它直接对应起来了。

3. UTF8使用的也非常普遍,它也是一种unicode的编码格式,它存在1/2/3/4个字节来表示一个文字。对于英文字符来说,使用空间非常小。 

4. UCS2与UTF16: UCS-2是UTF-16的子集,仅支持Unicode字符平面映射中的基本多文平面.占2个字节. 参考:http://hilojack.sinaapp.com/?p=1291

ANSI与GB2312

1. ANSI: unicode和ansi都是字符代码的一种表示形式,使用1-2字节表示一个字符。ANSI为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个字符。不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。

2. GB2312是一种本地化的编码格式,是ANSI字符代码的一种编码格式,相同的值,在其他本地语言体系里,表达的东西是不同的。《信息交换用汉字编码字符集》是由中国国家标准总局1980年发布,1981年5月1日开始实施的一套国家标准,标准号是GB 2312—1980。

参考:http://baike.baidu.com/view/443268.htm?fromId=25492

下面为转载内容:地址如下

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

-------------------------------------------------------------

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

作者: 阮一峰

今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料。

结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步搞清楚。

下面就是我的笔记,主要用来整理自己的思路。但是,我尽量试图写得通俗易懂,希望能对其他朋友有用。毕竟,字符编码是计算机技术的基石,想要熟练使用计算机,就必须懂得一点字符编码的知识。

1. ASCII码

我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从0000000到11111111。

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码,一直沿用至今。

ASCII码一共规定了128个字符的编码,比如空格"SPACE"是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

2、非ASCII编码

英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。比如,在法语中,字母上方有注音符号,它就无法用ASCII码表示。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。

但是,这里又出现了新的问题。不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。但是不管怎样,所有这些编码方式中,0--127表示的符号是一样的,不一样的只是128--255的这一段。

至于亚洲国家的文字,使用的符号就更多了,汉字就多达10万左右。一个字节只能表示256种符号,肯定是不够的,就必须使用多个字节表达一个符号。比如,简体中文常见的编码方式是GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示256x256=65536个符号。

中文编码的问题需要专文讨论,这篇笔记不涉及。这里只指出,虽然都是用多个字节表示一个符号,但是GB类的汉字编码与后文的Unicode和UTF-8是毫无关系的。

3.Unicode

正如上一节所说,世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。

可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是Unicode,就像它的名字都表示的,这是一种所有符号的编码。

Unicode当然是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字"严"。具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表。

4. Unicode的问题

需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

比如,汉字"严"的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。

这里就有两个严重的问题,第一个问题是,如何才能区别Unicode和ASCII?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

它们造成的结果是:1)出现了Unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示Unicode。2)Unicode在很长一段时间内无法推广,直到互联网的出现。

5.UTF-8

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种Unicode的实现方式。其他实现方式还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一。

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8的编码规则很简单,只有二条:

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

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

下表总结了编码规则,字母x表示可用编码的位。

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

下面,还是以汉字"严"为例,演示如何实现UTF-8编码。

已知"严"的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此"严"的UTF-8编码需要三个字节,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然后,从"严"的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,"严"的UTF-8编码是"11100100 10111000 10100101",转换成十六进制就是E4B8A5。

6. Unicode与UTF-8之间的转换

通过上一节的例子,可以看到"严"的Unicode码是4E25,UTF-8编码是E4B8A5,两者是不一样的。它们之间的转换可以通过程序实现。

在Windows平台下,有一个最简单的转化方法,就是使用内置的记事本小程序Notepad.exe。打开文件后,点击"文件"菜单中的"另存为"命令,会跳出一个对话框,在最底部有一个"编码"的下拉条。

里面有四个选项:ANSI,Unicode,Unicode big endian 和 UTF-8。

1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。

2)Unicode编码指的是UCS-2编码方式,即直接用两个字节存入字符的Unicode码。这个选项用的little endian格式。

3)Unicode big endian编码与上一个选项相对应。我在下一节会解释little endian和big endian的涵义。

4)UTF-8编码,也就是上一节谈到的编码方法。

选择完"编码方式"后,点击"保存"按钮,文件的编码方式就立刻转换好了。

7. Little endian和Big endian

上一节已经提到,Unicode码可以采用UCS-2格式直接存储。以汉字"严"为例,Unicode码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,就是Big endian方式;25在前,4E在后,就是Little endian方式。

这两个古怪的名称来自英国作家斯威夫特的《格列佛游记》。在该书中,小人国里爆发了内战,战争起因是人们争论,吃鸡蛋时究竟是从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。为了这件事情,前后爆发了六次战争,一个皇帝送了命,另一个皇帝丢了王位。

因此,第一个字节在前,就是"大头方式"(Big endian),第二个字节在前就是"小头方式"(Little endian)。

那么很自然的,就会出现一个问题:计算机怎么知道某一个文件到底采用哪一种方式编码?

Unicode规范中定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。这正好是两个字节,而且FF比FE大1。

如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。

8. 实例

下面,举一个实例。

打开"记事本"程序Notepad.exe,新建一个文本文件,内容就是一个"严"字,依次采用ANSI,Unicode,Unicode big endian 和 UTF-8编码方式保存。

然后,用文本编辑软件UltraEdit中的"十六进制功能",观察该文件的内部编码方式。

1)ANSI:文件的编码就是两个字节"D1 CF",这正是"严"的GB2312编码,这也暗示GB2312是采用大头方式存储的。

2)Unicode:编码是四个字节"FF FE 25 4E",其中"FF FE"表明是小头方式存储,真正的编码是4E25。

3)Unicode big endian:编码是四个字节"FE FF 4E 25",其中"FE FF"表明是大头方式存储。

4)UTF-8:编码是六个字节"EF BB BF E4 B8 A5",前三个字节"EF BB BF"表示这是UTF-8编码,后三个"E4B8A5"就是"严"的具体编码,它的存储顺序与编码顺序是一致的。

9. 延伸阅读

* The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets(关于字符集的最基本知识)

* 谈谈Unicode编码

* RFC3629:UTF-8, a transformation format of ISO 10646(如果实现UTF-8的规定)

以下是转载内容,转载地址:

http://hilojack.sinaapp.com/?p=1291

-----------------------------------------------------------------------------

04 五 13 字符编码入门

本文试图理清字符编码系统的整体结构.如有理解不对请指正.

字符编码

按照[现代的编码模型],字符编码的主要概念分为:有哪些字符(字符表)、它们的编号(编码字符集)、这些编号如何编码成一系列的“码元”(字符编码表)、这些码元如何组成八位字节流(字符编码方案).

字符表(Character Repotire)

一个系统所有抽象字符的集合,包括我们看得见的汉字/数字/符号和看不见的控制字符.unicode系统所使用的字符集是通用字符集UCS ,由ISO 10646所定义.

编码字符集(CCS:Coded Character Set)

将字符集C映射到非负整数(码位:编码字符的位置).如unicode字符平面映射.即完成对字符的编号.

unicode系统中的码位也叫unicode编码.

字符编码表(CEF:Caracter Encoding Form)

将码位转换成有限比特长度的整数值(码元/码值:字符编码的值)

在unicode系统中,其码位可被转换成8位串行的UTF-8,或者16位串行的UTF-16等等.也就说同一码位对应多个码值.
码元(Code Unit,也称“代码单元”)是指一个已编码的文本中具有最短的比特组合的单元。对于UTF-8来说,码元是8比特长;对于UTF-16来说,码元是16比特长;对于UTF-32来说,码元是32比特长。编码长度是码元的整数倍,如UTF-16的长度就是2字节/4字节(一对码元)

我们平时所说的UTF-8,UTF-16都处于字符编码表(CEF)的层面.

字符编码方案(CES:Caracter Encodeing Scheme)

定义如何将码值对应到8位组的串行,以便网络传输和文件存储.
这里有两个大背景:

  1. 对于多字节的UTF-16来说,windows是先读高字节再读低字节,而MAC则相反.为了标识字节顺序,就选择了一个字节序列标记(BOM:Byte Order Mark)来指定大端序(UTF-16 BE)和小端序(UTF-16).见UTF-16的编码模式
  2. 有些复杂的编码需要特别的方案:如ISO/IEC 2022需要使用转义串行,如SCSU、BOCU和Punycode需要压缩

在vim中,:%xxd 可查看相关字符的编码 :set fileencoding=**可对字符进行编码转换

unicode编码体系

unicode又名统一码、万国码、单一码、标准万国码

意义

因多语言环境的需要而诞生,它对应于ISO 10646通用字符集UCS,包括了其它所有字符集/已知语言的所有字符.

unicode与iso 10646

史上存在两个尝试创立单一字符集的组织:

  1. 国际标准化组织ISO——开发了ISO/IEC 10646项目
  2. 统一码联盟Unicode Consortium——开发了统一码项目

1991年前后,两个项目的参与者都认识到,世界不需要两个不兼容的字符集。于是,它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作.

到现在两个项目仍都存在,两者使用同一字符集,但二者本质上是不同的标准——unicode标准更为丰富,它额外定义了许多与字符相关的语义符号学,并且部分样例字形与iso 10646有显著区别。

unicode的编码和实现

一般,unicode编码系统分为编码方式(CCS)和实现方式(CEF/CES …).

unicode编码方式(CCS)

统一码(unicode)的编码方式使用的是通用字符集UCS. unicode字符的平面映射本质上就是CCS码位映射,即对字符的编号(ISO/IEC 10646-1所定义) (CCS)
这个码位就叫unicode编码.

  1. UCS-2:包含字符平面映射中的基本多文种平面,占16位,可表达2^16=65536个字符.2. UCS-4:其中已经定义了16个辅助平面.标准规定的UCS-4会占用32个字节,最高字节恒为0,可表达2^31个字符.
平面 始末字符值 中文名称 英文名称
0号平面 U+0000 – U+FFFF 基本多文种平面 Basic Multilingual Plane, 简称 BMP
1号平面 U+10000 – U+1FFFF 多文种补充平面 Supplementary Multilingual Plane, 简称 SMP
2号平面 U+20000 – U+2FFFF 表意文字补充平面 Supplementary Ideographic Plane, 简称 SIP
3号平面 U+30000 – U+3FFFF 表意文字第三平面(未正式使用[1] Tertiary Ideographic Plane, 简称 TIP
4号平面

13号平面
U+40000 – U+DFFFF (尚未使用)  
14号平面 U+E0000 – U+EFFFF 特别用途补充平面 Supplementary Special-purpose Plane, 简称 SSP
15号平面 U+F0000 – U+FFFFF 保留作为私人使用区(A区)[2] Private Use Area-A, 简称 PUA-A
16号平面 U+100000 – U+10FFFF 保留作为私人使用区(B区)[2] Private Use Area-B, 简称 PUA-B

实现方式(CEF/CES …)

在unicode编码体系中unicode码位转为实际存储的编码(码值)可以有不同实现方式.比如UTF8/UTF-16/UTF-32

在unicode体系中码位是唯一的,所以字符编码转换程序 在转码时 一般把码值转为unicode再转为其它的编码.

字节顺序标记(BOM)

BOM是用来标记字节序的. 在windows/mac中,UTF-16高低字节的存储顺序是不同的,为了以示区别,特别定义的大尾序和小尾序.同时在文件头部加入一个BOM头(Byte Order Mark).
对于UTF-8来说,它只是一个UTF-8编码记号(不建议使用,它会干扰很多程序的执行)

建议在编辑器中取消bom,比如在vim设置:set nobomb

编码 表示 (十六进制) 表示 (十进制)
UTF-8 EF BB BF 239 187 191
UTF-16(大端序) FE FF 254 255
UTF-16(小端序) FF FE 255 254
UTF-32(大端序) 00 00 FE FF 0 0 254 255
UTF-32(小端序) FF FE 00 00 255 254 0 0
UTF-7 2B 2F 76和以下的一个字节:[ 38 | 39 | 2B | 2F ] 43 47 118和以下的一个字节:[ 56 | 57 | 43 | 47 ]
en:UTF-1 F7 64 4C 247 100 76
en:UTF-EBCDIC DD 73 66 73 221 115 102 115
en:Standard Compression Scheme for Unicode 0E FE FF 14 254 255
en:BOCU-1 FB EE 28 及可能跟随着FF 251 238 40 及可能跟随着255
GB-18030 84 31 95 33 132 49 149 51
使用UTF-16编码的例子
编码名称 编码次序 编码
BOM ,
UTF-16LE 小尾序   31 67 2C 00 7F 80 69 D8 A5 DE
UTF-16BE 大尾序   67 31 00 2C 80 7F D8 69 DE A5
UTF-16 小尾序,包含BOM FF FE 31 67 2C 00 7F 80 69 D8 A5 DE
UTF-16 大尾序,包含BOM FE FF 67 31 00 2C 80 7F D8 69 DE A5

UTF-16/UCS-2

UTF-16是Unicode字符集的一种转换方式(Unicode Transfomation Format),它把unicode码位转为16比特长的码元.
字符长度:2个字节(16比特),4个字节(一对16比特码元)

UCS-2是UTF-16的子集,仅支持Unicode字符平面映射中的基本多文平面.占2个字节.

字符编码表(CEF)

对于unicoe基本多文平面(0×0000~0xffff).UTF-16的编码为一个16比特:

UTF-16 == Unicode(0x0~0xffff) #不含(0xd800~0xdfff),这个区保留给UTF-16的前导代理和后导代理

对于uncide辅助平面(0×10000~0x10ffff),UTF-16的编码为一对16比特字符串,由前导代理(lead surrogates)和后导代理(trail surrogates)组成.

将unicode码元(0x10000~0x10ffff)减去0x10000得到20位比特:0x0~0xfffff,这20位比特分高10位A(0~0x3ff)和低10位B(0~0x3ff)
UTF-16(lead surrogates) == A+0xd800 #值范围(0xd800~0xdbff)
UTF-16(trail surrogates) == B+0xd800 #值范围(0xdc00~0xdfff)

UTF-16字符匹配正则

根据UTF-16的CEF规则,我们可以得到关于匹配UTF-16字符的正则伪代码(这个正则是无法执行的,可执行的正则可比这个可复杂多了):

'#[\x{0000}-\x{d7ff}]
|[\x{e000}-\x{ffff}]
|([\x{d800}-\x{dbff}][\x{dc00}-\x{dfff}])#'

UTF-8

utf8以8位为单元对UCS进行编码,编码会占用1~4字节.与utf16所编码的英文字符相比,它的编码长度减少一半.

UTF-8 字符编码表CEF

代码范围
十六进制
标量值(scalar value)
二进制
UTF-8
二进制/十六进制
注释
000000 – 00007F
128个代码
00000000 00000000 0zzzzzzz 0zzzzzzz(00-7F) ASCII字符范围,字节由零开始
七个z 七个z
000080 – 0007FF
1920个代码
00000000 00000yyy yyzzzzzz 110yyyyy(C0-DF) 10zzzzzz(80-BF) 第一个字节由110开始,接着的字节由10开始
三个y;二个y;六个z 五个y;六个z
000800 – 00D7FF
00E000 – 00FFFF
61440个代码 [Note 1]
00000000 xxxxyyyy yyzzzzzz 1110xxxx(E0-EF) 10yyyyyy 10zzzzzz 第一个字节由1110开始,接着的字节由10开始
四个x;四个y;二个y;六个z 四个x;六个y;六个z
010000 – 10FFFF
1048576个代码
000wwwxx xxxxyyyy yyzzzzzz 11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz 将由11110开始,接着的字节由10开始
三个w;二个x;四个x;四个y;二个y;六个z 三个w;六个x;六个y;六个z

UTF-8优缺点

优点

  1. 保证搜索时一个字符的字符串不会出现在另一个字符的串里面.
  2. 兼容ASCII
  3. 抗干扰和稳定性好:一段两字节随机串行碰巧为合法的UTF-8而非ASCII的机率为32分1。对于三字节串行的机率为256分1,对更长的串行的机率就更低了

缺点

  1. 与UTF-16/gbk 想比,处理CJK字符串,编码长度不占优势

UTF-8正则匹配

当使用Perl时,可用以下的表达式测试页面是否使用了UTF-8编码:

m/\A(
[\x09\x0A\x0D\x20-\x7E]            # ASCII
| [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
|  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
|  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
|  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
|  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
)*\z/x;

utf8_unicode_ci和utf8_general_ci区别

utf8_unicode_ci的最主要的特色是支持扩展,即当把一个字母看作与其它字母组合相等时。例如,在德语和一些其它语言中‘ß’等于‘ss’。

utf8_general_ci是一个遗留的 校对规则,不支持扩展。它仅能够在字符之间进行逐个比较。这意味着utf8_general_ci校对规则进行的比较速度很快,但是与使用utf8_unicode_ci的校对规则相比,比较正确性较差)。

其它UTF

UTF-7

UTF-7是一种可变长度的字符编码方式,用以将UTF-16字符以ASCII编码.也就是说用修改的Base64(Modified Base64)去编码UTF-16字符.

因为SMTP作为基本邮件传输标准,只允许传输ASCII字符,过去很多邮件传输都使用UTF-7.自从MIME扩展了电子邮件标准之后,SMTP支持了其它字符集.现在绝大多数邮件服务商都使用UTF-8/GB2312/GB18030作为邮件字符编码.

严格来说 UTF-7 不能算是 Unicode 所定义的字符集之一,较精确的来说, UTF-7 是提供了一种将 Unicode 转换为 7 比特 US-ASCII 字符的转换方式
Modified Base64 与Base64的主要区别是结尾不会有”=”

UTF-7由于安全性薄弱,已经走入历史.

Gmail中文用户默认外发邮件编码(content-type)是GB2312(可改为UTF-8).其传输编码(Content-Transfer-Encoding)会按数据最短的原则选择: quoted-printable/base64或者不用.
腾讯邮箱用户默认的外发邮件编码是gb18030(可改为UTF-8).其传输编码使用的是base64.

UTF-32

UTF-32 是一个 UCS-4 的子集,使用32-比特的码值,只在0到10FFFF的字码空间(百万个码位)

内容传输编码(Content-Transfer-Encoding)

CTE由MIME定义,用于email数据传输.包括“7bit”,“8bit”,“binary”,“quoted-printable”,“base64”.其中常见的传输码为Base64/quoted-printable

Base64

Base64不是字符编码方案,而是一种基于64个可打印字符来表示二进制数据的表示方法.6bit(2^6=64)为一单元,对应一个可打印的字符.三个字节有24个位元.对应4个Base64字符.

编码规则

将二进制流/文本流以每6bit为一单元,3个字节为一组.以6bit(2^6=64)的数字大小为位置对应以下字符中的一个:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

如果最后剩余2个或1个字节,按以下方式补0:

文本 M a n
ASCII编码 77 97 110
二进制位 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
索引 19 22 5 46
Base64编码 T W F u

最后,如果剩下两个字节,在编码结果后加1个“=”;如果最后剩下一个字节,编码结果后加2个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

Quoted-printable

可打印字符引用编码(Quoted-printable,或QP encoding).
它使用ASCII字符表示各种字符编码–以便能个7bit or 8bit 数据通路上传输数据.
此编码为是MIME中 content transfer encoding的一种,用于email.(与base64并列为两种基本的邮件传输编码)

编码规则

Quoted-printable以8bit为单位进行编码,规则如下:

一般的8bit编码为"="加两个十六进制值,如"\x7A"编码为"=7A"
对于可打印的ascii码:0x21-0x7E("="号:0x3D除外),可用ASCII码直接表示
但是,如果水平制表符和空格符出现在行尾,必须用OP编码表示为"=09"(tab)和"=20"(space)
如果QP编码的数据每行长度超过76个字符,QP编码结果的每行结尾加一个软换行("=")

Gmail在发送以下字符时所使用的Content-Transfer-Econding正是QP,如果将其ContentType设置为:UTF-8.并发送邮件内容(“新”的utf8编码为\xe696b0):

新This is a test!
If you believe that truth=beauty, then surely mathematics is the most beautiful branch of philosophy.

那么,经过QP编码后的邮件text/plain原文为:

=E6=96=B0This is a test!
If you believe that truth=3Dbeauty, then surely mathematics is the most bea=
utiful branch of philosophy.

你很可能看到的是这个(因为你的邮件文本编辑器做format字符时就在most处断行了,使得单行不超过76个字符):

=E6=96=B0This is a test!
If you believe that truth=3Dbeauty, then surely mathematics is the most
beautiful branch of philosophy.

还有一个text/html原文.

与base64相比,如果Content-Type编码与ASCII是兼容的,那么QP编码后的邮件原文中ASCII是可读的.

GB相关的编码

本小节主要归纳汉字相关的编码:GB2312,GBK,GB18030.他们的关系如下图:

如图所示,GB18030基本兼容GBK.

GB2312

GB2312,也叫GB2312-80,于1981年推出.

特点

  1. 收录6763个汉字

编码结构

先对汉字进行分区(得到的编码叫区位码).

  1. 01-09区为特殊符号。
  2. 16-55区为一级汉字,按拼音排序。
  3. 56-87区为二级汉字,按部首/笔画排序。

编码:
对于ascii(0×00-0x7f)保持不变.
对于汉字和符号,使用两个字节表示:“高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0),“低位字节”使用了0xA1-0xFE(把01-94加上0xA0)

“啊”的区位码是0×1001,对应的gb2312就是0xb0a1

GBK

背景

因为原GB2312字符不足, 厂商微软利用GB 2312-80未使用的编码空间,收录GB 13000.1-93全部字符制定了GBK编码.

编码结构

对于GB2312字符保持不变,仅对Gb2312未使用的编码区进行了扩充.
对于双字节来说:第一字节的范围是81–FE(也就是不含80和FF),第二字节的一部分领域在40–7E,其他领域在80–FE.

GBK的编码范围
范围 第1字节 第2字节 编码数 字数
水准 GBK/1 A1A9 A1FE 846 717
水准 GBK/2 B0F7 A1FE 6,768 6,763
水准 GBK/3 81A0 40FE (7F除外) 6,080 6,080
水准 GBK/4 AAFE 40A0 (7F除外) 8,160 8,160
水准 GBK/5 A8A9 40A0 (7F除外) 192 166
用户定义 AAAF A1FE 564  
用户定义 F8FE A1FE 658  
用户定义 A1A7 40A0 (7F除外) 672  
合计:     23,940 21,886

按拼音排序

基于Gbk/Gb2312是按音序来编码的.可用此规则来对汉字进行拼音排序(以php为例)

//按拼音首字母排序
$arr = array(
'北京'=>'010',
'成都'=>'028',
);
ukrsort($arr, 'cmp');
var_dump($arr);
/**
*
* 比较拼音首字母(基于字符是按拼音顺序编码)
*/
function cmp(&$a, &$b) {
$a = iconv('utf-8', 'gbk', $a);
$a = $a[0];
$b = iconv('utf-8', 'gbk', $b);
$b = $b[0];
if ($a == $b) {
return 0;
}
return ($a > $b) ? 1 : -1;
}
function ukrsort(&$arr, $func) {
foreach ($arr as $k => $v) {
if (is_array($arr[$k])) {
ukrsort($arr[$k], $func);
}
}
uksort($arr, $func);
}

也可以通过编码找到绝大部分汉字的拼音首字母(以php为例)

/**
* 获取汉字拼音首字母(基于字符是按拼音顺序编码)
*/
function getFirstLetter($str) {
$fchar = ord($str{0});
if ($fchar >= ord("A") and $fchar <= ord("z"))
return strtoupper($str{0});
if (!is_string($str)) {
var_dump($str);
return;
}
$s1 = @iconv("UTF-8", "gbk", $str);
$s2 = @iconv("gbk", "UTF-8", $s1);
if ($s2 == $str) {
$s = $s1;
} else {
$s = $str;
}
$asc = ord($s{0}) * 256 + ord($s{1}) ;
if ($asc >= 45217 and $asc <= 45252)
return "A";
if ($asc >= 45253 and $asc <= 45760)
return "B";
if ($asc >= 45761 and $asc <= 46317)
return "C";
if ($asc >= 46318 and $asc <= 46825)
return "D";
if ($asc >= 46826 and $asc <= 47009)
return "E";
if ($asc >= 47010 and $asc <= 47296)
return "F";
if ($asc >= 47297 and $asc <= 47613)
return "G";
if ($asc >= 47614 and $asc <= 48118)
return "I";
if ($asc >= 48119 and $asc <= 49061)
return "J";
if ($asc >= 49062 and $asc <= 49323)
return "K";
if ($asc >= 49324 and $asc <= 49895)
return "L";
if ($asc >= 49896 and $asc <= 50370)
return "M";
if ($asc >= 50371 and $asc <= 50613)
return "N";
if ($asc >= 50614 and $asc <= 50621)
return "O";
if ($asc >= 50622 and $asc <= 50905)
return "P";
if ($asc >= 50906 and $asc <= 51386)
return "Q";
if ($asc >= 51387 and $asc <= 51445)
return "R";
if ($asc >= 51446 and $asc <= 52217)
return "S";
if ($asc >= 52218 and $asc <= 52697)
return "T";
if ($asc >= 52698 and $asc <= 52979)
return "W";
if ($asc >= 52980 and $asc <= 53688)
return "X";
if ($asc >= 53689 and $asc <= 54480)
return "Y";
if ($asc >= 54481 and $asc <= 55289)
return "Z";
return null;
}

GB18030

GB 18030,全称:国家标准GB 18030-2005《信息技术 中文编码字符集》,是中华人民共和国现时最新的内码字集(2005年发布).
有以下特点:

采用多字节编码,每个字可以由1个、2个或4个字节组成。
支持全部unicode(UCS)全部统一汉字.收录范围包含繁体汉字以及日韩汉字70244个
与GBK基本兼容,与GB 2312完全兼容

编码结构

  1. 单字节,其值从0到0x7F。
  2. 双字节,第一个字节的值从0×81到0xFE,第二个字节的值从0×40到0xFE(不包括0x7F)。
  3. 四字节,第一/三字节的值从0×81到0xFE,第二/四字节的值从0×30到0×39.

正则匹配

'#[\x00-\x7f]|[\x81-\xfe][\x40-0xfe]|([\x81-0xfe][\x30-\x39]){2}#'

参考

  1. 维基UCS
  2. 维基字符平面映射
  3. utf_bom
  4. 维基unicode
  5. 维基现代编码模型
  6. 维基UTF-16
  7. 维基UTF-8
  8. 维基GB2312
  9. 维基GBK
  10. 维基GB18030

(个人理解+转载)ANSI/ASCII/UTF8/UNICODE/GB2312/UCS-2/UTF16-文本的编码格式相关推荐

  1. linux unicode 转换工具,字符集之间转换(UTF-8,UNICODE,Gb2312)

    特搜集了UTF-8,UNICODE,Gb2312他们3个之间的相互转换. UTF-8:   3字节一个字符 UNICODE: 2字节一个字符 GB2312:  1字节一个字符 例子: "你& ...

  2. 转载 中文字符集编码Unicode ,gb2312 , cp936 ,GBK,GB18030

    转自: http://www.blog.edu.cn/user3/flyingcs/archives/2006/1418577.shtml 概要:UTF-8的一个特别的好处是它与ISO- 8859-1 ...

  3. UTF-8, Unicode, GB2312格式串转换之C语言版

    原住址:http://www.cnitblog.com/wujian-IT/archive/2007/12/13/37671.html           /*      author:   wu.j ...

  4. utf8转gb2312 c语言,UTF-8, Unicode, GB2312格式串转换之C语言版

    (申明:此文章属于原创,若转载请表明作者和原处链接 ) /*      author:   wu.jian   (吴剑)      English name: Sword /*      date:  ...

  5. 字符集之间转换(UTF-8,UNICODE,Gb2312) c++

    UTF-8:   3字节一个字符 UNICODE: 2字节一个字符 GB2312:  1字节一个字符 例子: "你"字的UTF-8编码: E4 BD A0 11100100 101 ...

  6. c++字符集之间转换(UTF-8,UNICODE,Gb2312)

    2019独角兽企业重金招聘Python工程师标准>>> UTF-8:   3字节一个字符 UNICODE: 2字节一个字符 GB2312:  1字节一个字符 例子: "你& ...

  7. 字符集和编码 UNICODE、ANSI、UTF-8、GB2312 都是什么鬼

    这是我在网上看到的一篇通俗易懂的教程,但是无法找到原作者的署名,故直接搬过来了 不是本人所作,特此声明 快下班时,爱问问题的小朋友Nico又问了一个问题: "sqlserver里面有char ...

  8. C++中UTF-8, Unicode, GB2312转换及有无BOM相关问题

    UTF-8转Unicode 首先,UTF-8和Unicode是有转换关系的,我们假设UTF-8字符串没有BOM. wstring UTF8toUnicode(const string &inp ...

  9. python3 gb2312转utf8_python2和python3字符编码 unicode,utf-8,gb2312相互转换encode,decode...

    一.预习: 1.Unicode 和utf-8之间的关系 unicode是一种编码标准,具体的实现标准可能是utf-8,utf-16,gbk -- UTF-8是Unicode的实现方式之一 2.pyth ...

  10. 统计“3_人民日报语料”文本中的字符数和词数,把文件分别保存为 ansi, UTF8,UTF16,unicode 格式

    统计"3_人民日报语料"文本中的字符数和词数,把文件分别保存为 ansi, UTF8,UTF16,unicode 格式; 首先,统计文件的字符数,有两种方法.第一种是将文件复制到w ...

最新文章

  1. 浙江大学计算机科学与技术学院工业设计工程,浙江大学考研·2020年工业设计考研信息整理...
  2. Elasticsearch入门和基本使用
  3. java常用代码总结
  4. 力扣—剑指 Offer 45. 把数组排成最小的数
  5. activiti 解压zip java.lang.IllegalArgumentException: MALFORMED 错误
  6. 狂人传记:戎马半生 何以安家
  7. 有k个list列表, 各个list列表的元素是有序的,将这k个列表元素进行排序( 基于堆排序的K路归并排序)...
  8. the vmrc console has disconnected attempting to reconnect
  9. js 对象拼接的方法 数组 Map Set
  10. DISM用于Win7部署的实验笔记
  11. Unity使用反射探头实现地面的镜面反射
  12. 三门问题的计算机模拟,三门问题和 JavaScript 仿真实验
  13. 汽车汽配行业供应链协同管理平台一体化管理,SCM供应链提升企业竞争力
  14. 用python建立三元一次方程组的解法_三元一次方程组的解法及运用
  15. 重庆网络公司的几种死法
  16. Ubuntu18.04 GoldenDict安装及配置
  17. java reactjs_[Java教程]Reactjs 入门基础(一)
  18. SQL Server 学习 SQL 语句 ( 二 )
  19. 看雪.Wifi万能钥匙 2017CTF年中赛---第一题
  20. 使用工具创建实体类出现的错误!Table configuration with catalog null, schema null, and table t_ssm_resource did not

热门文章

  1. 防止cookie 欺骗
  2. 文档无法保存 读取文档时出现问题(135)
  3. Error: Cannot find module ‘@/xxx‘
  4. 学习go语言里Duck typing 概念
  5. 计算机应用程序错误怎么解决办法,应用错误,教您怎么解决explorer.exe应用程序错误...
  6. CSS3阴影 box-shadow的使用和技巧总结
  7. 判断PPC或者SP平台
  8. 关服了的手游怎么进去_关服手游改成单机教程
  9. vb远程访问dde服务器,做wincc与VB的dde连接一定要用ddeserver吗?
  10. markdown如何生成一级标题