关于unicode:UTF-8,UTF-16和UTF-32

UTF-8, UTF-16, and UTF-32

utf-8、utf-16和utf-32有什么区别?

我知道它们都将存储Unicode,并且每个都使用不同的字节数来表示一个字符。选择一个比另一个有好处吗?


在ASCII字符代表文本块中大多数字符的情况下,UTF-8有一个优势,因为UTF-8将所有字符编码为8位(如ASCII)。它还有一个优点,即只包含ASCII字符的UTF-8文件与ASCII文件具有相同的编码。

在ASCII不占主导地位的情况下,UTF-16更好,因为它主要使用每个字符2个字节。对于高阶字符,UTF-8将开始使用3个或更多字节,而对于大多数字符,UTF-16仅保留2个字节。

UTF-32将以4个字节覆盖所有可能的字符。这使它非常膨胀。我想不出使用它有什么好处。


简而言之:

  • UTF-8:可变宽度编码,向后兼容ASCII。ASCII字符(U+0000到U+007F)取1字节,代码点U+0080到U+07FF取2字节,代码点U+0800到U+FFFF取3字节,代码点U+10000到U+10FFFF取4字节。适合英文文本,不适合中文文本。
  • UTF-16:可变宽度编码。代码点U+0000到U+ffff取2个字节,代码点U+10000到U+10ffff取4个字节。英文不好,中文不好。
  • UTF-32:固定宽度编码。所有代码点占用四个字节。一个巨大的记忆猪,但操作起来很快。很少使用。

长:参见维基百科:utf-8、utf-16和utf-32。


  • UTF-8是变量1到4字节。

  • UTF-16是变量2或4字节。

  • UTF-32固定为4个字节。


Unicode定义了一个巨大的字符集,为每个图形符号分配一个唯一的整数值(这是一个主要的简化,实际上不是真的,但对于这个问题来说,它已经足够接近了)。UTF-8/16/32是对其进行编码的不同方法。

简而言之,utf-32对每个字符使用32位值。允许他们对每个字符使用固定宽度的代码。

默认情况下,UTF-16使用16位,但这只会给您提供65K个可能的字符,这对于完整的Unicode集来说还远远不够。所以一些字符使用16位值对。

而utf-8默认使用8位值,这意味着127个第一个值是固定宽度的单字节字符(最高有效位用于表示这是多字节序列的开始,剩下7位用于实际字符值)。所有其他字符编码为最多4个字节的序列(如果内存可用)。

这就给我们带来了优势。任何ASCII字符都与UTF-8直接兼容,因此对于升级传统应用程序,UTF-8是一个常见而明显的选择。在几乎所有情况下,它也将使用最少的内存。另一方面,您不能保证字符的宽度。它可能是1、2、3或4个字符宽,这使得字符串操作变得困难。

UTF-32正好相反,它使用的内存最多(每个字符固定为4字节宽),但另一方面,您知道每个字符都有这个精确的长度,因此字符串操作变得简单多了。您可以从字符串的长度(以字节为单位)计算字符串中的字符数。用UTF-8不能这样做。

UTF-16是一个折衷方案。它允许大多数字符适合固定宽度的16位值。因此,只要没有中文符号、音符或其他符号,就可以假定每个字符的宽度为16位。它使用的内存比UTF-32少。但在某些方面,这是"两个世界中最糟糕的"。它几乎总是比UTF-8使用更多的内存,而且它仍然不能避免困扰UTF-8(可变长度字符)的问题。

最后,使用平台所支持的功能通常会有所帮助。Windows在内部使用UTF-16,所以在Windows上,这是一个显而易见的选择。

Linux有点不同,但它们通常对所有符合Unicode的内容都使用UTF-8。

所以简短的回答是:这三种编码都可以对相同的字符集进行编码,但它们将每个字符表示为不同的字节序列。


Unicode是一种标准,关于UTF-X,您可以将其视为一些实际用途的技术实现:

  • UTF-8-"大小优化":最适合基于拉丁字符的数据(或ASCII),每个字符只需要1个字节,但大小会相应地增加符号的多样性(在最坏的情况下,每个字符最多可以增加6个字节)
  • UTF-16-"平衡":每个字符至少需要2个字节,这足以满足现有的主流语言集的需要,并且具有固定的大小,以便于字符处理(但大小仍然是可变的,每个字符最多可以增长4个字节)
  • utf-32-"性能":允许使用简单的算法作为固定大小字符(4字节)的结果,但内存不足


我试着在博客上简单解释一下。

UTF 32

需要32位(4字节)来编码任何字符。例如,为了使用此方案表示"A"字符码位,需要用32位二进制数编写65:

1
00000000 00000000 00000000 01000001 (Big Endian)

如果仔细观察,您会注意到在使用ASCII方案时,最右边的7位实际上是相同的位。但是由于utf-32是固定宽度方案,我们必须附加三个字节。也就是说,如果我们有两个只包含"A"字符的文件,一个是ASCII编码的,另一个是UTF-32编码的,那么它们的大小将相应地为1字节和4字节。

UTF 16

许多人认为,由于utf-32使用固定宽度32位来表示代码点,所以utf-16是固定宽度16位。错了!

在UTF-16中,代码点可以用16位或32位表示。所以该方案是变长编码系统。与UTF-32相比有什么优势?至少对于ASCII,文件的大小不会是原始文件的4倍(但仍然是原始文件的两倍),所以我们仍然不能向后兼容ASCII。

由于7位足以表示"A"字符,我们现在可以使用2个字节,而不是像utf-32那样使用4个字节。看起来像是:

1
00000000 01000001

UTF-8

你猜对了……在UTF-8中,代码点可以用32、16、24或8位来表示,作为UTF-16系统,这个系统也是可变长度编码系统。

最后,我们可以用同样的方式表示"A",我们使用ASCII编码系统表示它:

1
01001101

一个小例子,其中utf-16实际上比utf-8好:

考虑中文字母"語"-其UTF-8编码为:

1
11101000 10101010 10011110

虽然它的UTF-16编码更短:

1
10001010 10011110

为了理解陈述及其解释方式,请访问原始帖子。


UTF-8

  • 没有字节顺序的概念
  • 每个字符使用1到4个字节
  • ASCII是编码的兼容子集
  • 完全自同步,例如流中任何位置的丢弃字节最多会损坏一个字符
  • 几乎所有的欧洲语言都是以两个字节或更少的字符编码的。

UTF 16

  • 必须用已知的字节顺序分析或读取字节顺序标记(BOM)
  • 每个字符使用2或4个字节

UTF 32

  • 每个字符4个字节
  • 必须用已知的字节顺序分析或读取字节顺序标记(BOM)

除非大部分字符来自CJK(中文、日文和韩文)字符空间,否则UTF-8将是最节省空间的字符。

UTF-32最适合按字符偏移量随机访问字节数组。


我做了一些测试来比较MySQL中utf-8和utf-16的数据库性能。

更新速度UTF-8

Enter image description here

UTF 16

Enter image description here

插入速度

Enter image description here

Enter image description here

删除速度

Enter image description here

Enter image description here


在UTF-32中,所有字符都用32位编码。其优点是可以轻松计算字符串的长度。缺点是,对于每个ASCII字符,您会浪费额外的三个字节。

在UTF-8字符中,长度可变,ASCII字符用一个字节(8位)编码,大多数西方特殊字符用两个字节或三个字节(例如欧元是三个字节)编码,更多的外来字符可以用四个字节。明显的缺点是,不能预先计算字符串的长度。但与UTF-32相比,编写拉丁(英语)字母文本所需的字节要少得多。

UTF-16也是可变长度的。字符可以用两个字节或四个字节编码。我真的不明白这一点。它的缺点是长度可变,但没有像UTF-8那样节省空间。

显然,在这三种技术中,UTF-8的传播最为广泛。


根据开发环境的不同,您甚至可能无法选择在内部使用什么编码字符串数据类型。

但是对于存储和交换数据,如果您有选择的话,我总是使用UTF-8。如果您有大部分的ASCII数据,这将为您提供最少的数据传输量,同时仍然能够对所有数据进行编码。优化最少的I/O是现代机器的发展方向。


如前所述,差异主要是基础变量的大小,在每种情况下,基础变量的大小都会变大,以允许更多的字符被表示。

然而,字体、编码和事情都非常复杂(不必要吗?),因此需要一个大链接来更详细地填写:

http://www.cs.tut.fi/~jkorpela/chars.html ascii

不要期望理解所有这些,但是如果你以后不想有问题,那就应该尽早地尽可能多地学习(或者让别人帮你解决)。

保罗。


简而言之,使用utf-16或utf-32的唯一原因是分别支持非英语和古脚本。

我想知道为什么有人会选择非UTF-8编码,因为它显然更有效地用于Web/编程目的。

一个常见的误解-后缀数字并不能说明它的能力。它们都支持完整的Unicode,就像UTF-8可以用一个字节处理ASCII一样,这样对CPU和Internet来说效率更高/更低。

一些好的读物:http://www.personal.psu.edu/ejp10/blogs/gotcunicode/2007/10/which-utf-do-i-use.html以及http://utf8everywhere.org