UTF-8,UTF-16和UTF-32 Unicode编码可以存储的字符数是否有所不同?

时间:2020-03-06 14:41:37  来源:igfitidea点击:

好的。我知道这看起来像是典型的"他为什么不只是谷歌浏览它还是去www.unicode.org进行查找?"问题,但是对于这样一个简单的问题,在检查了两个来源之后,答案仍然难以理解。

我非常确定这三个编码系统都支持所有Unicode字符,但是在演示文稿中声明之前,我需要进行确认。

额外的问题:这些编码在可扩展支持的字符数方面是否有所不同?

解决方案

如有疑问,我个人经常查看Joel的有关unicode,编码和字符集的文章。

UTF-8,UTF-16和UTF-32都支持全套Unicode代码点。没有一个字符支持但另一个字符不支持。

至于额外的问题"这些编码在可扩展以支持的字符数方面是否有所不同?"是的,没有。 UTF-8和UTF-16的编码方式将它们可以支持的代码点总数限制为少于2 ^ 32. 但是,Unicode联盟不会将无法在UTF-8或者UTF-16中表示的代码点添加到UTF-32. 这样做会违反编码标准的精神,并且无法保证从UTF-32到UTF-8(或者UTF-16)的一对一映射。

不,它们只是不同的编码方法。它们都支持对同一组字符进行编码。

UTF-8每个字符使用1到4个字节的任意位置,具体取决于我们要编码的字符。 ASCII范围内的字符仅占一个字节,而非常不寻常的字符占四个字节。

UTF-32每个字符使用四个字节,而不管它是什么字符,因此它将始终比UTF-8使用更多空间来编码相同的字符串。唯一的优点是我们可以仅通过计数字节来计算UTF-32字符串中的字符数。

UTF-16的大多数字符使用两个字节,异常字符使用四个字节。

http://en.wikipedia.org/wiki/Comparison_of_Unicode_encodings

所有UTF-8 / 16/32编码都可以映射所有Unicode字符。请参阅Wikipedia的Unicode编码比较。

IBM的这篇文章以UTF-8编码XML文档非常有帮助,并且指出如果可以选择的话,最好选择UTF-8. 主要原因是广泛的工具支持,并且UTF-8通常可以通过不知道unicode的系统。

在" IBM文章中的规格说明"部分中:

Both the W3C and the IETF have
  recently become more adamant about
  choosing UTF-8 first, last, and
  sometimes only. The W3C Character
  Model for the World Wide Web 1.0:
  Fundamentals states, "When a unique
  character encoding is required, the
  character encoding MUST be UTF-8,
  UTF-16 or UTF-32. US-ASCII is
  upwards-compatible with UTF-8 (an
  US-ASCII string is also a UTF-8
  string, see [RFC 3629]), and UTF-8 is
  therefore appropriate if compatibility
  with US-ASCII is desired." In
  practice, compatibility with US-ASCII
  is so useful it's almost a
  requirement. The W3C wisely explains,
  "In other situations, such as for
  APIs, UTF-16 or UTF-32 may be more
  appropriate. Possible reasons for
  choosing one of these include
  efficiency of internal processing and
  interoperability with other
  processes."

众所周知,UTF-8,UTF-16和UTF-32都可以对所有Unicode代码点进行编码。但是,UCS-2(有时错误地称为UCS-16)变体无法实现,例如,这是我们发现的变体。在Windows XP / Vista中。

有关更多信息,请参见Wikipedia。

编辑:我对Windows是错误的,NT是唯一支持UCS-2的计算机。但是,许多Windows应用程序会像UCS-2中那样在每个代码点假定一个单词,因此我们很可能会发现错误。参见另一篇Wikipedia文章。 (感谢JasonTrue)

没有Unicode字符可以用一种编码存储,而不能以另一种编码存储。这仅仅是因为有效的Unicode字符已被限制为可以在UTF-16中存储的字符(这是三种编码中最小的容量)。换句话说,与UTF-16相比,UTF-8和UTF-32可以表示更大范围的字符,但事实并非如此。请阅读以获得更多详情。

UTF-8

UTF-8是可变长度代码。一些字符需要1个字节,一些字符需要2个,一些3个,还有一些4个。每个字符的字节被简单地一个接一个地写成连续的字节流。

虽然某些UTF-8字符可以是4个字节长,但UTF-8无法编码2 ^ 32个字符。还差得远我将尽力解释其原因。

读取UTF-8流的软件仅获得一个字节序列,应如何确定接下来的4个字节是单个4字节字符,两个2个字节字符还是四个1个字节字符(或者某些其他组合)?基本上,这是通过确定某些1字节序列不是有效字符,而某些2字节序列不是有效字符来完成的,依此类推。当这些无效序列出现时,假定它们构成了较长序列的一部分。

我敢肯定,我们已经看到了一个截然不同的示例:这被称为转义。在许多编程语言中,都确定字符串源代码中的\字符不会转换为字符串"已编译"形式的任何有效字符。当在源中找到\时,它被认为是更长序列的一部分,例如\ n或者\ xFF。注意," \ x"是无效的2个字符序列,而" \ xF"是无效的3个字符序列,但是" \ xFF"是有效的4个字符序列。

基本上,要在具有多个字符和具有较短字符之间进行权衡。如果要2 ^ 32个字符,则平均长度必须为4个字节。如果我们希望所有字符都等于或者小于2个字节,则字符数不能超过2 ^ 16. UTF-8给出了一个合理的折衷方案:所有ASCII字符(ASCII 0至127)均以1字节表示,这对于兼容性很有用,但是允许更多的字符。

与大多数可变长度编码(包括上面所示的转义序列的类型)一样,UTF-8是瞬时代码。这意味着,解码器仅逐字节读取,并且一旦到达字符的最后一个字节,就知道该字符是什么(并且知道它不是更长字符的开始)。

例如,字符" A"使用字节65表示,并且没有两个/三/四字节字符的第一个字节为65. 否则,解码器将无法分辨除" A"之外的那些字符",然后再说其他的话。

但是UTF-8受到进一步限制。它确保了较短字符的编码永远不会出现在较长字符的编码内的任何位置。例如,一个4字节字符中的所有字节都不能为65.

由于UTF-8具有128个不同的1字节字符(其字节值为0-127),因此所有2、3和4字节字符必须仅由128-256范围内的字节组成。这是一个很大的限制。但是,它允许面向字节的字符串函数几乎不需要修改就可以工作。例如,如果C的strstr()输入是有效的UTF-8字符串,则它始终可以按预期工作。

UTF-16

UTF-16也是可变长度代码;其字符占用2或者4个字节。保留0xD800-0xDFFF范围内的2字节值,用于构造4字节字符,并且所有4字节字符均由0xD800-0xDBFF范围内的两个字节,然后是0xDC00-0xDFFF范围内的2个字节组成。因此,Unicode不会在U + D800-U + DFFF范围内分配任何字符。

UTF-32

UTF-32是固定长度的代码,每个字符为4个字节长。虽然这允许对2 ^ 32个不同的字符进行编码,但是在此方案中仅允许使用0到0x10FFFF之间的值。

容量比较:

  • UTF-8:2,097,152(实际上为2,166,912,但由于设计细节,其中一些映射到同一事物)
  • UTF-16:1,112,064
  • UTF-32:4,294,967,296(但限于前1,114,112)

因此,最受限制的是UTF-16!正式的Unicode定义将Unicode字符限制为可以使用UTF-16编码的Unicode字符(即,范围U + 0000至U + 10FFFF,但U + D800至U + DFFF除外)。 UTF-8和UTF-32支持所有这些字符。

实际上,UTF-8系统被"人为地"限制为4个字节。它可以扩展为8个字节,而不会违反我之前概述的限制,这将产生2 ^ 42的容量。实际上,原始的UTF-8规范最多允许6个字节,其容量为2 ^ 31. 但是RFC 3629将其限制为4个字节,因为要覆盖UTF-16的所有工作,这需要多少字节。

还有其他(主要是历史性的)Unicode编码方案,尤其是UCS-2(只能将U + 0000编码为U + FFFF)。