UTF-8,UTF-16和UTF-32可以存储的字符数不同吗?

问题描述 投票:45回答:6

好的。我知道这看起来像典型的“为什么他不只是谷歌它或去www.unicode.org并查找它?”问题,但对于这样一个简单的问题,在检查了两个来源之后,答案仍然存在。

我很确定所有这三种编码系统都支持所有Unicode字符,但我需要在演示文稿中声明之前确认它。

奖金问题:这些编码在可以扩展到支持的字符数量方面是否有所不同?

unicode character-encoding utf
6个回答
39
投票

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

UTF-8使用每个字符一到四个字节的任何位置,具体取决于您编码的字符。 ASCII范围内的字符只占用一个字节,非常不寻常的字符占用四个字符。

UTF-32每个字符使用四个字节,无论它是什么字符,因此它总是使用比UTF-8更多的空间来编码相同的字符串。唯一的优点是您可以通过仅计算字节数来计算UTF-32字符串中的字符数。

UTF-16对大多数字符使用两个字节,对于不常见字符使用四个字节。

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


56
投票

没有Unicode字符可以存储在一个编码中而不能存储在另一个编码中。这只是因为有效的Unicode字符被限制为可以存储在UTF-16中的内容(UTF-16具有三种编码中最小的容量)。换句话说,UTF-8和UTF-32可用于表示比UTF-16更广泛的字符,但它们不是。请阅读以获得更多详情。

UTF-8

UTF-8是可变长度代码。一些字符需要1个字节,一些字符需要2个字节,一些字符串需要3个字节。每个字符的字节只是作为连续的字节流一个接一个地写入。

虽然一些UTF-8字符长度可以是4个字节,但UTF-8不能编码2 ^ 32个字符。它甚至都不是很接近。我会试着解释一下这个的原因。

读取UTF-8流的软件只获取一个字节序列 - 如何判断接下来的4个字节是单个4字节字符,还是两个2字节字符,或者4个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是一个instantaneous code。这意味着,解码器只是逐字节读取,一旦到达字符的最后一个字节,它就知道字符是什么(并且它知道它不是更长字符的开头)。

例如,字符'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编码的那些(即,范围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)。


7
投票

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

至于奖金问题“这些编码的字符数是否可以扩展到支持?”是的,不是。 UTF-8和UTF-16的编码方式将它们可以支持的代码点总数限制为小于2 ^ 32。但是,Unicode Consortium不会向UTF-32添加无法用UTF-8或UTF-16表示的代码点。这样做会违反编码标准的精神,并且无法保证从UTF-32到UTF-8(或UTF-16)的一对一映射。


5
投票

我个人总是在有疑问时检查Joel's post有关unicode,编码和字符集的信息。


4
投票

所有UTF-8/16/32编码都可以映射所有Unicode字符。见Wikipedia's Comparison of Unicode Encodings

这篇IBM文章Encode your XML documents in UTF-8非常有用,并表明如果您有选择,最好选择UTF-8。主要原因是广泛的工具支持,UTF-8通常可以通过不知道unicode的系统。

IBM article中的规格说明:

W3C和IETF最近都更加坚定地选择UTF-8,包括前一个,最后一个,有时只选择UTF-8。万维网的W3C字符模型1.0:基础知识,“当需要一个独特的字符编码时,字符编码必须是UTF-8,UTF-16或UTF-32.US-ASCII向上兼容UTF- 8(US-ASCII字符串也是UTF-8字符串,参见[RFC 3629]),因此如果需要与US-ASCII兼容,则UTF-8是合适的。“实际上,与US-ASCII的兼容性非常有用,几乎是一项要求。 W3C明智地解释说,“在其他情况下,例如API,UTF-16或UTF-32可能更合适。选择其中一种的可能原因包括内部处理的效率和与其他过程的互操作性。”


2
投票

正如大家所说,UTF-8,UTF-16和UTF-32都可以编码所有Unicode代码点。但是,UCS-2(有时被错误地称为UCS-16)变体不能 ,这是你找到的那个,例如在Windows XP / Vista中 。

有关更多信息,请参阅Wikipedia

编辑:我错了Windows,NT是唯一一个支持UCS-2的人。但是,许多Windows应用程序将假定每个代码点只有一个单词,如UCS-2,因此您可能会发现错误。见another Wikipedia article。 (感谢JasonTrue)

© www.soinside.com 2019 - 2024. All rights reserved.