字符编码基础知识

本文主要是对字符编码相关基础知识的系统梳理,通过系统地了解字符编码的相关知识,能对很多由编码不匹配引起的乱码等问题有更深入地理解。

字符集与字符编码

字符集

字符集是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同。

字符编码

由于计算机只能识别二进制数据,如果计算机要准确的处理各种字符集,则需要将字符数据转换为二进制数据。而字符编码规定了如何将字符流转换为字节流。

区别

在Unicode出现之前,字符集与字符编码的区分并不明显,因为同一个字符集只有一种编码方式,如ASCII既可以指代字符集也可以指代字符编码。

而Unicode字符集出现后,由于它支持多种编码方式,才开始区分这两者。在Unicode下,字符集指的是Unicode,字符编码则指UTF-8、UTF-16、UTF-32。

ASCII

American Standard Code for Information Interchange,美国信息交换标准代码。现今最通用的单字节编码系统,用于显示现代英语和其他西欧语言。

特点

7位(bits)表示一个字符,共128字符,字符值从0到127,其中32到126是可显示字符(英文大小写字符、阿拉伯数字和西文符号),其它是控制字符(回车、退格、换行等)。

ASCII扩展字符集

由于7位编码的字符集只能支持128个字符,为了表示更多的常用字符,各国家和厂商为自己定制了ASCII扩展字符集。ASCII扩展字符集在标准ASCII的基础上,使用8位(bits)表示一个字符,最多能支持256个字符。

ISO-8859

由于各公司、国家之间都有自己的ASCII扩展字符集,同一个数值,在不同的字符集之间表示的符号可能不一样。这样在一台电脑上正常可以阅读的文件,到另外一台电脑可能就成了乱码。为了解决这个问题,ISO组织统一了一套标准,就是ISO-8859。不过 ISO-8859 不是一个字符集,而是一系列扩充的ASCII码字符集,如下:

ISO/IEC 8859-1 (Latin-1) - 西欧语言
ISO/IEC 8859-2 (Latin-2) - 中欧语言
ISO/IEC 8859-3 (Latin-3) - 南欧语言。世界语也可用此字符集显示。
ISO/IEC 8859-4 (Latin-4) - 北欧语言
ISO/IEC 8859-5 (Cyrillic) - 斯拉夫语言
ISO/IEC 8859-6 (Arabic) - 阿拉伯语
ISO/IEC 8859-7 (Greek) - 希腊语
ISO/IEC 8859-8 (Hebrew) - 希伯来语(视觉顺序)
ISO 8859-8-I - 希伯来语(逻辑顺序)
ISO/IEC 8859-9(Latin-5 或 Turkish)- 它把Latin-1的冰岛语字母换走,加入土耳其语字母。
ISO/IEC 8859-10(Latin-6 或 Nordic)- 北日耳曼语支,用来代替Latin-4。
ISO/IEC 8859-11 (Thai) - 泰语,从泰国的 TIS620 标准字集演化而来。
ISO/IEC 8859-13(Latin-7 或 Baltic Rim)- 波罗的语族
ISO/IEC 8859-14(Latin-8 或 Celtic)- 凯尔特语族
ISO/IEC 8859-15 (Latin-9) - 西欧语言,加入Latin-1欠缺的芬兰语字母和大写法语重音字母,以及欧元(€)符号。
ISO/IEC 8859-16 (Latin-10) - 东南欧语言。主要供罗马尼亚语使用,并加入欧元符号。

MBCS

上面说的ASCII、ASCII扩展字符集、ISO-8859中每个字符都是一个字节(8-bit)可以表示的,所以称为单字节字符集(Single-Byte Character Set,简称SBCS)。

而在亚洲,中、日、韩等国家,文字的数量远超256个,继续使用单字节字符集已经无法满足需求,于是他们制定了自己的字符集。使用2个或以上的字节数表示自己的字符集,这就是多字节字符集(Multi-Bytes Character Sets,简称MBCS)。

GB2312、Big5、GBK、GB18030

GB2312

GB2312是由中国国家标准总局1980年发布的一套国家标准,共收录6763个汉字,并收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。但对于人名、古汉语等方面出现的罕用字,GB2312不能处理,这导致了后来GBK及GB18030字符集的出现。

Big5

Big5,又称为大五码或五大码,是由台湾五大厂商宏碁、神通、佳佳、零壹以及大众一同制定的一种繁体中文编码方案,是使用繁体中文社区中最常用的电脑汉字字符集标准,共收录13,060个汉字。

GBK

GBK编码,是在GB2312基础上的内码扩展规范,完全兼容GB2312,支持国际标准ISO/IEC10646-1和国家标准GB13000-1中的全部中日韩汉字,并包含了BIG5编码中的所有汉字。

GB18030

GB18030是我国政府于2000年3月17日发布的新的汉字编码国家标准,2001年8月31日后在中国市场上发布的软件必须符合本标准。它收录了27484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。并且与Unicode 3.0版本兼容,填补Unicode扩展字符字汇“统一汉字扩展A”的内容。并且与以前的国家字符编码标准(GB2312,GB13000.1)兼容。

ANSI

在windows系统中,ANSI编码代表本地编码的意思。起初,ANSI本来只包含英文编码,后来到了各国,在ANSI编码基础上对各国语言做了扩展,所以ANSI编码也可以指本地编码。就是说,在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。

Unicode

如上面所述,世界上存在着多种字符编码,同一个码值,在不同的编码体系里代表着不同的字符。当信息在国际间交流时,无法将属于多种语言的文字,存储在同一种编码体系的文本中。

要自由使用不同语言就必须有一个新编码,为各种文字统一分配编码。ISO(国际标准化组织)和Unicode协会(一个软件制造商的协会)分别开始了这个工作,即ISO的Universal Coded Character Set(UCS)项目,和Unicode协会的Unicode项目。后来它们开始合并了双方的工作成果,采用相同的字库和字码,但目前两个项目都存在并独立地公布自己的标准。

任何文字在Unicode中都对应一个值, 这个值称为代码点(code point)。Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U+”,例如字母“A”的编码为 004116 ,所以“A”的编码书写为“U+0041”。

UCS-2、UCS-4

UCS-2和UCS-4定义了Unicode中文字和代码点之间的对应关系。

UCS-2用两个字节来表示代码点,其取值范围为 U+0000~U+FFFF。

为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。 它的范围为 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是一样的。

UTF-8、UTF-16、UTF-32

UTF是 Unicode Tranformation Format,即把Unicode转做某种格式的意思。用于在UCS-2或UCS-4基础上将十六进制数表示的码点转换为能用于传输和存储的二进制序列。

UTF-8

UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,以8位为单元编码UNICODE字符。

编码方式

如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的字节数,其余各字节均以10开头。

Unicode/UCS-4bit数UTF-8byte数
0000 ~007F0~70XXX XXXX1
0080 ~07FF8~11110X XXXX10XX XXXX2
0800 ~FFFF12~161110XXXX10XX XXXX10XX XXXX3
1 0000 ~1F FFFF17~211111 0XXX10XX XXXX10XX XXXX10XX XXXX4
UTF-16 和 UTF-32

UTF-16,UTF-32分别用16位和32位为单位编码UNICODE字符。

UTF-16编码在UCS-2的U+0000~U+FFFF范围中等同于UCS-2,UTF-32基本等同于UCS-32。

但UCS-2,UCS-4只是编码方案,UTF-16,UTF-32却要用于实际的传输,所以就不得不考虑字节序的问题。

字节序和BOM
字节序

Little endian(LE):将低序字节存储在起始地址;Big endian(BE):将高序字节存储在起始地址。

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

BOM

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

在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。

这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。

UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。

总结

字符编码的标准是在不断进步的,总的来说,可大致分为三类:

1、以ASCII为代表的单字节编码,如ASCII,ASCII扩展,ISO-8859下一系列编码;

2、以GBK为代表的多字节编码,如GB2312,GBK, GB18030等;

3、以Unicode为代表的统一编码体系,支持任何语言文字,将字符码值与编码方式分离,一套码值可以对应多套编码方式,如UTF-8,UTF-16等;

参考文档:

https://baike.baidu.com/item/字符编码/8446880?fr=aladdin

https://baike.baidu.com/item/ASCII

https://baike.baidu.com/item/Unicode

https://baike.baidu.com/item/UTF-8

https://www.cnblogs.com/notbecoder/p/4840783.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值