本地化入门 | 不懂“字符集”和“字符编码”?读这篇就够了!

转自:翻译技术沙龙

近来经常有老师和同学们咨询“本地化”有关的话题,希望沙龙君分享一下。那今天就先说说本地化最基本的入门知识:字符集字符编码

为什么要先讲字符集和字符编码呢?因为要做本地化,首先要知道各个国家/地区的文字和符号是怎么在计算机上进行存储和显示的。

为了帮助大家理解,还是先举个例子。假设我们使用的是中文版 Windows 10 操作系统。打开记事本程序,输入以下内容,然后保存:

这时候跳出来一个警示页面。几个意思呢?就是里面的内容不都是ANSI编码的,还有Unicode格式的。不理它,点击确定看看。

惨!立马打脸了。原来的版权符号© 变成问号了。看来还是不能忽视警告信息。

重来一遍,这次保存时选择“另存为”。

然后选择编码。这时候,出现好几个选项。如何选择呢?我们暂时先选择UTF-8,这次可以正常保存版权符号了。其他的选项后面再解释。

如果不使用记事本,我们试试文本编辑器 EmEditor。在EmEditor中选择Save As,更改 Encoding,会出现以下界面。

现在,大家对于字符编码是什么,是不是稍微有了一点感觉了?下面我们进入正式的学习。

第一部分:基本概念

字节

字节(Byte)是计算机用来计量存储容量的一种计量单位。我们知道,计算机只能识别1和0组成的二进制位。一个数就是1位(bit)。为了方便计算,规定8位就是一个字节。

例如:10101010这个8位二进制就占用了一个字节的存储容量。

字符

字符(Character)和字节不一样。字符是各种文字和符号的总称,包括各个国家/地区的文字、数字、标点符号、图形符号等。但是,一个字符在计算机中占用多少字节,是与编码方式有关的。采用不同的编码方式,占用的内存不一样。

例如:符号加号+是一个字符,汉字“翻译”是两个字符。在GBK编码中一个汉字占2个字节,在UTF-8编码中一个汉字占3个字节。

编码规范

原本计算机只能显示0和1这样的二进制数。随着计算机走入寻常百姓家,人们当然希望能在计算机上直接显示字符。于是国际组织就制定了编码规范,希望使用不同的二进制数来代表不同的字符,这样计算机就可以根据二进制数来显示对应的字符。

例如:GBK 编码规范,就可以让计算机在二进制数和中文字符之间相互转换。而使用GBK编码就可以使计算机显示中文字符。

字库表

一套编码规范不一定包含世界上所有的字符,每套编码规范都有自己适用的场景。而字库表就存储了某种编码规范中能显示的所有字符。计算机根据二进制数从字库表中找到与之对应的字符,然后显示给用户。字库表相当于一个存储字符的数据库。

例如:几乎所有汉字都保存在GBK 编码规范的字库表中,所以可以显示汉字。但法语、俄语并不在该字库表中,所以使用GBK编码的文档不能正常显示法语、俄语等不包含在其字库表中的字符。

字符集

在一个字库表中,每一个字符都有一个对应的二进制地址,而字符集(Character Set)就是这些地址的集合。字符集定义了字符和二进制的对应关系,为每个字符分配了唯一的编号。可以将字符集理解成一个很大的表格,它列出了所有字符和二进制的对应关系,计算机显示文字或者存储文字,就是一个查表的过程。

字符编码

由于计算机只能识别二进制数据,若要准确处理各种字符集,则需要将字符数据转换为二进制数据。而字符编码规定了如何将字符流转换为字节流,如何将字符的编号存储到计算机中。如果使用了类似 GB2312 和 GBK 的变长存储方案(不同的字符占用的字节数不一样),那么为了区分一个字符到底使用了几个字节,就不能将字符的编号直接存储到计算机中。字符编号在存储之前必须要经过转换,在读取时还要再逆向转换一次,这套转换方案就叫做字符编码。

字符集与字符编码的区别

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

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

到这里先简单总结一下:

编码过程:字库表中的一个文字或符号,在字符集中找到对应的二进制串,然后通过一种编码方式,存储到计算机存储设备中。

解码过程:一个二进制数,通过一种编码方式,转换成编码字符集中正常的地址,然后在字库表中找到一个对应的字符,最终显示给用户。

第二部分:常见的字符编码规范

2.1 单字节字符集(Single-Byte Character Set,简称SBCS)

ASCII

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码),是最早产生的编码规范,也是如今最通用的单字节编码系统,用于显示现代英语和其他西欧语言。

它用7位(bits)二进制表示(00000000-01111111,即0x00-0x7F),可以看出ASCII码只需要1个字节的存储空间。没有特定的编码方式,直接使用地址对应的二进制数来表示,或者干脆就称之为ASCII 编码方式。共128个字符,字符值从0到127,其中32到126是可显示字符(英文大小写字符、阿拉伯数字和西文符号),其他是控制字符(回车、退格、换行等)。

EASCII

EASCII(Extended ASCII,ASCII扩展字符集),由于7位编码的字符集只能支持128个字符,为了表示更多的常用字符,各个国家/地区和厂商为自己定制了ASCII扩展字符集。ASCII扩展字符集在标准ASCII的基础上,使用8位(bits)二进制(00000000-11111111,即0x00-0xFF)来表示一个字符,最多能支持256个字符。

ISO-8859

由于各国家/地区和各个公司之间都有自己的ASCII扩展字符集,这就造成同一个数值有可能在不同的字符集之间表示的符号是不一样的。这样一来,在一台电脑上可以正常阅读的文件,到另外一台电脑上可能就成了乱码。

为了解决这个问题,国际标准化组织在ASCII的基础上进行了扩展,形成了ISO-8859标准。跟EASCII类似,兼容ASCII,在高128个码位上有所区别。

ISO-8859-1编码范围使用了单字节内的所有空间,在支持ISO-8859-1的系统中传输和存储其他任何编码的字节流都不会被抛弃。换言之,把其他任何编码的字节流当作ISO-8859-1编码看待都没有问题。ASCII编码是一个7位的容器,ISO-8859-1编码是一个8位的容器。

由此可见,ISO-8859-1只占1个字节,因此ISO-8859-1是不支持中文的。

ISO-8859 标准不是一个字符集,而是一系列扩充的ASCII码字符集。由于欧洲的语言环境十分复杂,所以根据各地区的语言又形成了很多子标准,ISO-8859-1、ISO-8859-2、ISO-8859-3、……、ISO-8859-16。

具体如下:

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) - 东南欧语言。主要供罗马尼亚语使用,并加入欧元符号。

我们最开始的例子中,EmEditor就展示出了这些主要的编码。

SBCS

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

2.2 双字节字符集(Double-Bytes Character Sets,简称DBCS)

当计算机传到了亚洲的中、日、韩等国家,文字的数量远超256个,单字节字符集的256个码位无法满足需求。于是继续扩大二维表,单字节改双字节,16位二进制数,65536个码位。在不同国家/地区又制定了自己的字符集,中国大陆地区的GB2312、中国香港特别行政区和台湾地区的BIG5、日本的Shift JIS,韩国的Euc-kr等等。

GB2312

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

Big5

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

GBK

GBK全称《汉字内码扩展规范》,是在GB2312-80标准基础上建立的内码扩展规范,使用了双字节编码方案,其编码范围从8140至FEFE(剔除xx7F),共23940个码位,共收录了21003个汉字,完全兼容GB2312-80标准,支持国际标准ISO/IEC 10646-1和国家标准GB13000-1中的全部中日韩汉字,并包含了BIG5编码中的所有汉字。

GBK字符集中所有字符占2个字节,不论中文英文都是2个字节。没有特殊的编码方式,习惯称呼GBK编码。一般在国内,汉字较多时使用。

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 编码。

2.3 多字节字符集(Multi-Bytes Character Sets,简称MBCS)

当互联网席卷了全球,地域限制被打破了,不同国家/地区的计算机在交换数据的过程中,由于之前出现的各种不同的编码方式,文本就会出现乱码的问题。

历史上存在两个独立的、尝试创立单一字符集的组织,即国际化标准组织(ISO)和多语言软件制造商组成的Unicode联盟。前者开发的 ISO/IEC 10646 项目,即UCS字符集;后者开发的Unicode项目,即最初的Unicode字符集。因此两个组织最初制定了不同的标准。

UCS(Universal Character Set)

通用字符集(Universal Character Set,UCS)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的字符编码方式。UCS字符集包括了所有其他字符集。它保证了与其他字符集的双向兼容,即,如果你将任何文本字符串翻译到UCS格式,然后再翻译回原编码,你不会丢失任何信息。UCS包含了已知语言的所有字符。

Unicode字符集

最初的Unicode字符是多语言软件制造商组成的Unicode联盟开发的一套包括所有世界上文字和符号的字符集。但1991年前后,ISO和Unicode联盟两个项目的参与者都认识到,世界不需要两个不兼容的字符集。于是,他们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。

从Unicode 2.0开始,Unicode采用了与ISO 10646-1相同的字库和字码;ISO也承诺,ISO 10646将不会替超出U+10FFFF的UCS-4编码赋值,以使得两者保持一致。

当前两个项目仍都存在,并独立地公布各自的标准。但Unicode联盟和ISO/IEC JTC1/SC2都同意保持两者标准的码表兼容,并紧密地共同调整任何未来的扩展。在发布的时候,Unicode一般都会采用有关字码最常见的字型,但ISO 10646一般都尽可能采用Century字型。

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

UCS-2、UCS-4

UCS对应两种编码:对每一个字符采用四个8比特字节编码的称为UCS-4,对每一个字符采用两个8比特字节编码的称为UCS-2。UCS-2和UCS-4定义了Unicode中的文字和代码点之间的对应关系。

UCS-2用两个字节来表示代码点,其取值范围为 U+0000~U+FFFF。例如“翻”的编码是U+7FFB,“译”的编码是U+8BD1。

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

UTF-8、UTF-16、UTF-32

Unicode定义了全球文字的唯一编号,是字符集。TF是 Tranformation Format,即把Unicode转做某种格式的意思。而UTF-8、UTF-16、UTF-32就是基于Unicode字符集的具体编码方式,也就是说Unicode定义了一个字符由一串具体的二进制数字组成,而UTF-8、UTF-16、UTF-32则定义了怎样将代表这个字符的二进制数字串存储到计算机。

为什么会有UTF-8、UTF-16、UTF-32的区别?由于Unicode最多可以保存4个字节容量的字符。也就是说,要区分每个字符,每个字符的地址需要4个字节,显然这是十分浪费存储空间的,于是就有了不同编码方式,如UTF-8,UTF-16,UTF-32编码。

UTF-8

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

编码方式

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

UTF-16 和 UTF-32

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

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

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

字节序和BOM

字节序

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

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

UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。

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,UTF-32等。

(文中部分内容引自网络,原始出处不详。如涉版权,请联系小编。)


关注微信公众号“语言服务行业”,了解更多语言服务行业与翻译技术相关的资讯和洞察~

你可能感兴趣的:(本地化入门 | 不懂“字符集”和“字符编码”?读这篇就够了!)