手机版

Unicode编码秘密

时间:2021-09-10 来源:互联网 编辑:宝哥软件园 浏览:

如果你是一个生活在2003年的程序员,你不知道字符、字符集、编码和Unicode的基本知识。那你应该小心。如果我抓到你,我会罚你在潜艇里剥洋葱六个月。

这个邪恶的威胁是乔尔斯波尔斯基十年前首次发出的。遗憾的是,很多人认为他只是在开玩笑,所以很多人仍然不能完全理解Unicode以及Unicode、UTF-8和UTF-16之间的区别。这就是我写这篇文章的原因。

在离家更近的地方,想象一下,在一个阳光明媚的下午,你收到一封高中毕业后失去联系的朋友发来的电子邮件,邮件附件为txt格式(也称为纯文本格式)。此附件包含以下二进制位字符串:

复制代码如下:010010001001010011001100010010011001100011000110001100011000111

Email的正文是空的,更加神秘。在启动通用文本编辑器打开此附件之前,您是否考虑过文本编辑器如何将二进制形式翻译成字符?有两个关键问题:

1.字节是如何分组的?(例如1字节字符和2字节字符)

2.一个或多个字节如何映射到字符?

这些问题的答案在本文档(字符编码)中。一般来说,编码定义了两件事:

1.字节如何分组,如8位或16位,也称为编码单位。

2.编码单位和字符之间的映射关系。例如,在ASCII码中,十进制65被映射到字母a。

字符编码和字符集略有不同。但是通常它与你无关,除非你正在设计一个底层的库。

ASCII是上个世纪最流行的编码系统之一,至少在西方是这样。下图显示了ASCII码中的编码单位是如何映射到字符的。

即使在有经验的程序员中,一个常见的误解是纯文本使用ASCII码,每个字符是8位。

事实是没有这样的“明文”。如果内存或硬盘中有不知道编码的字符串,则无法翻译或显示。绝对没有第二条路。

那么当你刚收到的附件没有指定编码格式的时候,电脑会怎么翻译呢?这是否意味着你永远无法读懂一个失去联系的老朋友想告诉你的话?在我们找到答案之前,让我们回到那个时候,——3354,当时钱能买到的最大硬盘是29MB。

历史回顾

很久以前,计算机制造商有他们自己的字符表示方式。他们不需要担心如何与其他计算机通信,并提出了自己在屏幕上渲染字形的方法。随着计算机的日益普及,制造商之间的竞争更加激烈,在不同的计算机系统之间转换数据是非常痛苦的。人们已经厌倦了这种定制带来的混乱。

最后,计算机制造商制定了一个描述字符的标准方法。他们定义了使用一个字节的低7位来表示字符,并制作了一个如上所示的查找表来将7位的值映射到一个字符。比如字母A是65,C是99,~是126等等,由此ASCII码诞生了。最初的ASCII标准定义了从0到127的字符,正好可以用7位来表示。但是没有持续多久.

为什么选择7位而不是8位来表示一个字符?我不在乎。但是一个字节就是八位,也就是说一位没有被使用,也就是说128到255的编码没有被ASCII标准制定者规定,这些美国人对世界其他地方一无所知,甚至不关心。

其他国家的人借此机会开始使用128到255之间的代码来用自己的语言表达字符。例如,144是阿拉伯语ASCII码,而它是俄语ASCII码。即使在美国,未使用区域也有各种用途。IBM PC出现了“OEM字体”或“扩展ASCII码”,为用户提供了漂亮的图形字符来绘制文本框,并支持一些欧洲字符,如英镑()符号。

同样,ASCII的问题是,尽管每个人都同意使用字符0-127,但对字符128-255有许多不同的解释。您必须告诉计算机使用哪种ASCII码才能正确显示128到255之间的字符。

这对于北美人和英国岛民来说不是问题,因为无论使用哪种样式的ASCII码,拉丁字母的显示都是一样的。英国人仍然需要面对的问题是,原来的ASCII码不包含英镑符号,但这无关紧要。

与此同时,亚洲更令人头疼。亚洲语言有更多的字符和字形需要存储,一个字节是不够的。因此,他们开始使用两个字节来存储字符,这被称为DBCS(双字节编码方案)。在DBCS,操纵琴弦变得非常痛苦。你应该怎么做?

这些问题已经成为系统开发人员的噩梦。例如,MS DOS必须支持所有风格的ASCII,因为他们想把软件卖给其他国家。他们提出了“内部码表”的概念。例如,您需要告诉DOS(通过使用“chcp”命令)您想要使用保加利亚内部代码表,然后它才能显示保加利亚字母。内部代码表的替换将应用于整个系统。对于用多种语言工作的人来说,这是一个问题,因为他们必须经常在几个内部代码表之间来回切换。

虽然内部代码表是一个好主意,但它不是一个简单的解决方案,它只是一种黑客技术或简单的修改,以使编码系统工作。

进入Unicode的世界

最后,美国人意识到应该提出一个标准方案,用世界上所有语言显示所有字符,以减轻程序员的痛苦,避免字符编码带来的第三次世界大战。为此,Unicode诞生了。

Unicode背后的思想非常简单,但却被广泛误解。Unicode就像一本电话簿,标记了字符和数字之间的映射关系。乔尔称它们为“神奇数字”,因为它们可能是随机分配的,不会给出任何解释。官方术语是Code Point,它总是以u开头。理论上,每种语言中的每个字符都被Unicode协会赋予了一个神奇的数字。例如,希伯来语的第一个字母是U 2135,字母a是U 0061。

Unicode不涉及字符如何用字节表示,它只指定字符对应的数字,仅此而已。

对Unicode的其他误解包括:Unicode支持的最大字符数是65536,Unicode字符必须占用两个字节。告诉你这些的人应该改变主意。

请记住,Unicode只是字符和数字映射的标准。它不限制支持的字符数,也不要求字符占用两个、三个或任何其他字节数。

如何将Unicode字符编码成内存中的字节是另一个主题,由UTF (Unicode转换格式)定义。

Unicode编码

两种最流行的Unicode编码方案是UTF-8和UTF-16。让我们看看他们的细节。

UTF-8

UTF-8是一个非常惊人的概念,它漂亮地实现了与ASCII代码的向后兼容,以确保Unicode可以被公众接受。不管是谁发明的,至少应该获得诺贝尔和平奖。

在UTF-8中,字符0-127由1字节表示,使用与美国ASCII相同的编码。这意味着80年代写的文档可以用UTF-8打开,没有任何问题。只有字符128及以上由2、3或4字节表示。因此,UTF-8被称为可变长度编码。

回到文章开头的问题,来自老朋友附件的字节流如下:复制代码如下:0100100001010011000010010010010010010011111

这个字节流表示ASCII和UTF-8中相同的字符:你好

UTF-16

另一种流行的可变长度编码方案是UTF-16,它使用2或4个字节来存储字符。然而,人们逐渐意识到UTF-16可能会浪费存储空间,但那是另一个话题。

低端(小端)和高端(大端)

Endian发音为endian或印度语。这个术语的起源可以追溯到《格列佛游记》。(小说中,小人国主张煮鸡蛋应该从大端剥还是从小端剥,争论双方分别称为“大端派”和“小端派”。)

低字节顺序和高字节顺序只是在内存中存储和读取一个字节(称为字)的约定。这意味着,当您让计算机使用UTF-16在内存中存储字母A(两个字节)时,您使用的字节顺序方案决定了您是将第一个字节放在第二个字节之前还是之后。这有点难以理解。我们来看一个例子:当您使用UTF-16保存来自朋友的附件时,它的后半部分在不同的系统中可能是这样的:

00 68 00 65 00 6C 00 6C 00 6F(高字节顺序,高字节存在于前面)

68 00 65 00 6C 00 6C 00 6F 00 6F00(低位字节顺序,低位字节存在于前面)

字节顺序方案只是微处理器架构师的偏好。例如,英特尔使用低字节顺序,摩托罗拉使用高字节顺序。

字节顺序标记

如果你经常需要在高字节序和低字节序系统之间转换文档,想要区分字节序,还有另一个奇怪的约定叫做BOM。BOM是一个设计巧妙的字符,用在文档的开头,告诉读者文档的字节顺序。在UTF-16中,它是通过将FE FF放在第一个字节中来实现的。在不同字节顺序的文档中,会显示为FF FE或FE FF,明确告诉解释者这个文档的字节顺序。

BOM虽然很有用,但不是很简洁,因为有一个类似的概念叫“Magic Byte”,多年来一直用来表示文档的格式。BOM和魔术词的关系还没有明确界定,有些解释者会混淆。

恭喜你读了这篇文章。你一定是个耐心的读者。

还记得文章开头的问题吗,既然没有“纯文本”文档,为什么你的文本编辑器和浏览器每次都能正确显示内容?答案是,软件欺骗了你,这就是为什么这么多人对编码一无所知。当软件无法确定编码时,它会猜测。大多数时候,它会猜测是覆盖ASCII的UTF-8,还是ISO-8859-1,或者任何其他可以想象的字符集。因为英语中使用的拉丁字母几乎可以在包括UTF-8在内的所有字符集内显示,即使编码错误,英语字母看起来也是正确的。

但是,如果您在浏览网页时看到一个符号,这意味着此网页的编码不是您的浏览器猜到的编码。此时,您可以单击浏览器中的查看——字符编码菜单来尝试不同的编码。

摘要

如果你没有时间阅读整篇文章,或者你只是略读了前面的内容。然后请确保您能理解以下内容:

这个世界上从来没有明文这种东西。如果你想读一个字符串,你必须知道它的编码。

Unicode是将字符映射到数字的简单标准。Unicode协会将帮助您处理所有幕后问题,包括为新字符分配编码。

Unicode不会告诉你字符是如何编码成字节的。这由编码方案决定,并由UTF指定。

最重要的是:

始终记得通过内容类型或元数据集标记明确指定文档的编码。这样,浏览器就不需要猜测您使用的编码,它们将准确地使用您指定的编码来呈现文档。

版权声明:Unicode编码秘密是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。

相关文章推荐