如何解释unicode编码

时间:2017-06-24 21:04:31

标签: character-encoding

我刚读完Joel Spolsky的文章"The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)"

我非常感谢对文章这一部分的澄清。

  

好的,所以说我们有一个字符串:Hello,在Unicode中,对应于这五个代码点:    U + 0048 U + 0065 U + 006C U + 006C U + 006F ......这就是编码的来源。

     

Unicode编码最早的想法导致了关于这两个字节的神话,嘿,让我们将这些数字分别存储在两个字节中。所以Hello成为

     

00 48 00 65 00 6C 00 6C 00 6F

     

右?没那么快!不可能也是:

     

48 00 65 00 6C 00 6C 00 6F 00?

     

嗯,从技术上讲,是的,我相信它可以,事实上,早期的实现者希望能够以高端或低端模式存储他们的Unicode代码点,无论他们的特定CPU速度最快,而且,这是晚上,那是早上,已经有两种存储Unicode的方法。因此,人们不得不想出在每个Unicode字符串的开头存储FE FF的奇怪惯例;这被称为Unicode字节顺序标记,如果你交换你的高字节和低字节,它将看起来像一个FF FE,读取你的字符串的人将知道他们必须交换每隔一个字节。唷。并非每个Unicode字符串都在开头都有一个字节顺序标记。

我的问题:

为什么0048开头的两个零点可以移到结尾?

什么是FE FF和FF FE,它们之间的区别是什么以及它们是如何使用的? (是的,我试过谷歌搜索这些条款,但我仍然感到困惑)

他为什么然后说" Phew。并非每个Unicode字符串都在开头都有一个字节顺序标记。"?

另外,我非常感谢任何推荐的资源,以了解有关此内容的更多信息。

2 个答案:

答案 0 :(得分:2)

摘要: 0xFEFF(字节顺序标记)字符用于解决某些字符编码的字节序问题。但是,今天的大多数字符编码都不容易出现字节序问题,因此字节顺序标记与今天并不相关。

  

为什么0048开头的两个零点可以移到结尾?

如果所有字符都使用两个字节,则每个字符都保存在计算机内存中的2字节数据结构中。字节(8位组)是大多数计算机存储器中的基本可寻址单元,每个字节都有自己的地址。在使用 big-endian 格式的系统上,字符0x0048将以下列方式保存在两个1字节的内存单元中:

 n    n+1
+----+----+
| 00 | 48 |
+----+----+

此处,nn+1是存储单元的地址。因此,在big-endian系统上,最重要的字节存储在数据结构的最低内存地址中。

另一方面,在 little-endian 系统上,字符0x0048将按以下方式存储:

 n    n+1
+----+----+
| 48 | 00 |
+----+----+

因此,在little-endian系统上,最低有效字节存储在数据结构的最低内存地址中。

因此,如果大端系统向您发送字符0x0048(例如,通过网络),它会向您发送字节序列00 48。另一方面,如果little-endian系统向您发送字符0x0048,它会向您发送字节序列48 00

因此,如果您收到类似00 48的字节序列,并且您知道它代表一个16位字符,则需要知道发件人是大端还是小 - 端序系统。在第一种情况下,00 48表示字符0x0048,在第二种情况下,00 48表示完全不同的字符{{1} }。

这是0x4800 FE序列的来源。

  

什么是FE FF和FF FE,它们之间的区别是什么以及它们是如何使用的?

FF是Unicode byte-order mark (BOM),在我们的2字节编码示例中,这将是16位字符U+FEFF

惯例是所有系统(big-endian和little-endian)都将字符0xFEFF保存为任何文本流的第一个字符。现在,在big-endian系统上,此字符表示为字节序列0xFEFF FE(假设内存地址从左到右增加),而在小端系统上,它表示为FF FF

现在,如果您阅读了按照此约定创建的文本流,则您知道第一个字符必须是FE。因此,如果文本流的前两个字节是0xFEFF FE,则您知道此文本流是由 big-endian 系统创建的。另一方面,如果前两个字节是FF FF,则您知道文本流是由 little-endian 系统创建的。在任何一种情况下,您现在都可以正确解释流的所有2字节字符。

  

他为什么然后说" Phew。并非每个Unicode字符串都在开头都有一个字节顺序标记。"?

在每个文本流的开头放置字节顺序标记(BOM)字符FE只是一种约定,并非所有系统都可以遵循它。因此,如果缺少BOM,则存在不知道是否将2字节字符解释为big-endian或little-endian的问题。

  

另外,我非常感谢任何推荐的资源,以了解有关此内容的更多信息。

备注:

今天,使用最广泛的Unicode兼容编码是UTF-8。 UTF-8旨在避免字节序问题,因此,整个字节顺序标记0xFEFF内容与UTF-8无关(请参阅here)。 / p>

然而,字节顺序标记与其他与Unicode兼容的编码UTF-16UTF-32相关,这些编码容易出现字节序问题。如果浏览可用编码列表,例如在文本编辑器或终端的设置中,您会看到有UTF-16和UTF-32的big-endian和little-endian版本,通常称为UTF-16BE和UTF-16LE,或UTF-32BE和UTF-32LE。但是, UTF-16和UTF-32在实践中很少使用

今天使用的其他流行编码包括来自ISO 8859 series的编码,例如ISO 8859-1(和派生的Windows-1252),称为Latin-1,或者纯{{3}编码。但是,所有这些都是单字节编码,也就是说,每个字符编码为1个字节并保存在1字节数据结构中。因此,字节顺序问题在这里并不适用,字节顺序标记故事也与这些情况无关

总而言之,你努力理解的字符编码的字节序问题因此大多具有历史价值,并且不再与今天的世界真正相关

答案 1 :(得分:1)

这与计算机内存中数据的内部存储有关 - 在本例中(00 48),一些计算机将首先存储最大字节,然后存储最小字节(称为big-endian) ),其他人将首先存储最小字节(little-endian)。因此,根据您的计算机,当您读取内存中的字节数时,您将首先获得00或者先获得48。而且你需要知道它将采用哪种方式来确保你正确地解释字节。有关该主题的更深入介绍,请参阅维基百科上的Endianness(https://en.wikipedia.org/wiki/Endianness

现在,大多数编译器和口译员会为您处理这些低级别的东西,因此您很少(如果有的话)需要担心它。