字符编码

位、字节、字符

  • 位(bit b)指二进制中的一位,是二进制最小信息单位。

  • 字节(Byte B)是计算机信息技术用于计量存储容量的一种计量单位。

  • 字符( Character )是指计算机中使用的字母、数字、汗字和符号等。

字符集和字符编码

  • 字符集(Charset):是一个系统支持的所有抽象字符的集合。

  • 字符编码(Character Encoding):是一套法则,使字符集与计算机之间建立对应关系,就是将字符转换为计算机可以接受的数字代码。就是以二进制的数字来对应字符集的字符。

常用字符集

ASCII

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。

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

ASCII编码:将ASCII字符集转换为计算机可以接受的数字系统的数的规则。使用7位(bits)表示一个字符,共128字符。

ASCII只是为英语国家的人使用的编码,因为里面只是用到了英语常用的字符

ISO-8859-1

ISO-8859-1编码是单字节编码,向下兼容ASCII,是ASCII 的扩展的一种,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。

此字符集支持部分于欧洲使用的语言,包括阿尔巴尼亚语、巴斯克语、布列塔尼语、加泰罗尼亚语、丹麦语、荷兰语、法罗语、弗里西语、加利西亚语、德语、格陵兰语、冰岛语、爱尔兰盖尔语、意大利语、拉丁语、卢森堡语、挪威语、葡萄牙语、里托罗曼斯语、苏格兰盖尔语、西班牙语及瑞典语。

Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。

GB 2312

《信息交换用汉字编码字符集》是由中国国家标准总局1980年发布,1981年5月1日开始实施的一套国家标准,标准号是GB 2312—1980。

GB2312编码适用于汉字处理、汉字通信等系统之间的信息交换,通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB 2312。

基本集共收入汉字6763个和非汉字图形字符682个。

GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。对于人名、古汉语等方面出现的罕用字,GB2312不能处理,这导致了后来GBK及GB 18030汉字字符集的出现。

GB2312简体中文编码表

BIG5

Big5是在1984年由台湾13家厂商与台湾地区财团法人信息工业策进会为五大中文套装软件(宏碁、神通、佳佳、零壹、大众)所设计的中文内码,所以就称为Big5中文内码。

大五码是使用繁体中文社群中最常用的电脑汉字字符集标准,共收录13,060个中文字,其中有二字为重覆编码。

Unicode

总数已经超过了65535,所以2个字节的数字是不够用的。

Unicode编码系统为表达任意语言的任意字符而设计。它使用4字节的数字来表达每个字母、符号,或者表意文字(ideograph)。

Unicode 还不断在扩增, 每个新版本插入更多新的字符。直至目前为止的第六版,Unicode 就已经包含了超过十万个字符。

Unicode是字符集,UTF-32/ UTF-16/ UTF-8是三种字符编码方案。

Unicode与utf8是什么关系?

Unicode是字符集,UTF-32/ UTF-16/ UTF-8是三种字符编码方案。

字符编码

GB2312编码

GB2312简体中文编码表

如何进行编码?

GB2312一个汉字用两个字节表示。

原则上,两个字节可以表示 256×256=65536 种不同的符号。

考虑到汉字编码与其它国际通用编码,如ASCII 西文字符编码的关系,我国国家标准局采用了加以修正的两字节汉字编码方案,只用了两个字节的低7位。这个方案可以容纳 128×128=16384 种不同的汉字;

为了与标准ASCII码兼容,每个字节中都不能再用32个控制功能码和码值为32的空格以及127的操作码。

所以每个字节只能有94个编 码。这样,双七位实际能够表示的字数是:94×94=8836个。

注意为了与标准ASCII码兼容,每个字节中都不能再用32个控制功能码和码值为32的空格(特殊字符位,33个)以及1码值为127的操作码(1个,backspace),所以128-33-1=94,所以仅剩下94×94=8836个。94个区,94个位。

区位码、国标码、机内码

区位码

这个方阵实际上组成一个有94个区(编号由01到94),每个区有94个位(编号由01到94)的汉字字符集。

一个汉字所在的区号和位号的组合就构成了该汉字的"区位码"。其中,高两位为区号,低两位为位号。这样区位码可以唯一地确定某一汉字或字符;

反之,任何一个汉字或符号都对应一个唯一的区位码,没有重码。如“保”字在二维代码表中处于17区第3位,区位码即“1703 ”。

国标码

国标码是由区位码稍作转换得到,是一个汉字国家标准的二进制编码。

其转换方法为:先将十进制区码和位码转换为十六进制的区码和位码;

这样就得了一个与国标码有一个相对位置差的代码,再将这个代码的第一个字节和第二个字节分别加上20H,就得到国标码。

如:“保”字的国标码为3123H,它是经过下面的转换得到的:1703D->1103H->+20H->3123H。 (20h就是十进制的32,上文提到了“但为了与标准ASCII码兼容,每个字节中都不能再用32个控制功能码和码值为32的空格以及127的操作码”)

知识提示:

  • 十六进制中H,就是表示数值是以16进制表示的。

  • O为8进制;

  • D是10进制,一般简略掉;

  • B是二进制。

解析过程: 1. 1703 十进制的区位码,分别转为16进制 17十进制 =>11十六进制(11H),03十进制=> 03十六进制 (03H),即为1103H 2. 再将第一个字节和第二个字节分别加上20H,11H+20H = 31H,03H+20H=23H,即3123H

机内码

国标码是汉字信息交换的标准编码,但因其前后字节的最高位为0,与ASCII码发生冲突,如 “保”字,国标码为31H和23H,而西文字符“1”和“#”的SCII也为31H和23H,现假如内存中有两个字节为31H和23H;

这到底是一个汉字,还是两个西文字符“1”和“#”?于是就出现了二义性,显然,国标码是不可能在计算机内部直接采用的。

于是汉字的机内码采用变形国标码,其变换方法为:将国标码的每个字节都加上128,即将两个字节的最高位由0改1,其余7位不变,如:由上面我们知道,“保”字的国标码为3123H,前字节为00110001B,后字节为00100011B,高位改1为10110001B和10100011B 即为B1A3H,因此,保字的机内码就是B1A3H;。机内码是一个汉字在计算机内部保存的编码。

Unicode与 UCS

国际标准化组织(ISO)、多语言软件制造商组成的统一码联盟。

unicode,为了世界上大多数文字系统进行整理和编码。

ISO组织也在做同样的事情, ISO开展了 ISO/IEC 10646项目,名字叫“ Universal Multiple-Octet Coded Character Set”,简称UCS。

后来,双方意识到世界不需要2套通用的字符集,所以双方开始进行整合,到unicode2.0时,unicode的编码和ucs的编码都基本一致。

unicode编码与UTF

一个字符的Unicode编码是确定的。

但是在实际传输过程中,由于不同系统平台的设计不一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。Unicode的实现方式称为Unicode转换格式(Unicode Translation Format,简称为UTF)。

简单说UCS或Unicode只是定义了从0到1114112这些数字各自对应是什么字符,而计算机上是如何实现的就是由UTF决定的。

UTF-8、 UTF-16、 UTF-32等都是Unicode的编码实现方式。

图:Unicode中的汉字片段

重要:Unicode中的汉字组成并不像GBK一样按照汉语拼音来的,并没有什么明显的规律,所以在UTF-8中,汉字要得到汉字的拼音的话是办不到的,这时候要把他转换成GBK,然后再获取汉字的拼音。

UTF-8 编码方式(规则)

UNICODE 区域对照表

通过查看上面链接的区域对照表,中国属于4E00-9FFF CJK Unified Ideographs 中日韓統一表意文字

由上图可见属于0800-FFF中,

UTF-8中汉字到底占几个字节? 3个字节

手工把Unicode转为UTF-8的编码

  1. “你好” 的unicode码 “ 20320 ” “ 22909 ”

  2. 二进制: 100 111101 100000 , 101 100101 111101

  3. 每个字从右往左填充 1110xxxx 10xxxxxx 10xxxxxx

  4. 计算器二进制转换为16进制:E4 BD A0 , E5 A5 BD

解析:

工具:在线进制转换

  1. 通过Unicdoe【真正的完整码表】对照表(二)汉字Unicode表 查找到 “你”的16进制为4F60 ,转换成十进制为20320, “好”的位置是十六进制是5960+1D = 597D ,转换成十进制为22909

  2. “你好” 的unicode码 十进制分别为 “ 20320 ” “ 22909 ”

  3. 转成二进制为00 111101 100000 , 101 100101 111101,从上图中汉字属于0800-FFF中,UTF-8字节流为1110xxxx 10xxxxxx 10xxxxxx

  4. 每个字从右往左填充 1110xxxx 10xxxxxx 10xxxxxx(就是把xxx的)

11100100 10111101 10100000 , 11100101 10100101 10111101 5. 采用在线转换工具,计算器二进制转换为16进制:E4 BD A0 , E5 A5 BD

练习把unicode转为UTF-8

“北京” 的unicode码 “21271” , “20140”

第一步:计算器算出每个字的二进制

第二步:填充 1110xxxx 10xxxxxx 10xxxxxx

第三步:计算器二进制转换为16进制

第四步:16进制编辑填入结果,然后以UTF-8查看

UTF-16

  • UTF-16和上面提到的Unicode本身的编码规范是一致的。

  • 所有字符的编码长度为16位,也即2个字节。

  • 对ASCII字符来说,存储空间浪费严重。

  • 不兼容ASCII。

UTF的字节序和BOM

UTF-16编码每个字符占用了两个字节,在Macintosh (Mac)机和PC机上,对字节顺序的理解是不一致的。避免同一个文件造成错乱如何解决呢?

Unicode规范中推荐的标记字节顺序的方法是BOM( Byte Order Mark )。

在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?

Unicode规范中推荐的标记字节顺序的方法就是BOM。

UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。

BOM含义

开头字节 Charset/encoding

EF BB BF UTF-8

FE FF UTF-16/UCS-2, little endian(UTF-16LE)

FF FE UTF-16/UCS-2, big endian(UTF-16BE)

FF FE 00 00 UTF-32/UCS-4, little endian.

00 00 FE FF UTF-32/UCS-4, big-endia

总结:

  • 区位码前两个位换成十六进制,然后后两位换成十六进制。

  • 国际码=区位码(十六进制)+2020H

  • 机内码=国际码+8080H

  • 01-09区为特殊符号。

16-55区为一级汉字,按拼音排序。

56-87区为二级汉字,按部首/笔画排序。

10-15区 及88-94区则未有编码。

资料

UNICODE与UTF-8的转换详解

Last updated