UTF-8、UTF-16 和 UTF-32

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

提问人: 提问时间:1/31/2009 最后编辑:Peter Mortensen 更新时间:5/11/2023 访问量:317391

问:

UTF-8、UTF-16 和 UTF-32 之间有什么区别?

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

Unicode UTF-16 UTF UTF-32

评论

70赞 10/1/2013
如果您对 Unicode 的工作原理感兴趣,请观看此视频 youtube.com/watch?v=MijmeoH9LT4
1赞 mins 7/3/2014
该视频的重点是 UTF-8,是的,它很好地解释了可变长度编码的工作原理,并且主要与仅读取或写入固定长度 ASCII 的计算机兼容。Unicode 人员在设计 UTF-8 编码时很聪明。
2赞 Kotauskas 5/30/2019
UTF-8 是大多数现代软件中保存文件的事实标准。更具体地说,它是 HTML 以及配置和翻译文件使用最广泛的编码(例如,Minecraft 不接受其所有文本信息的任何其他编码)。UTF-32 对于内部存储器表示来说速度很快,而 UTF-16 有点被弃用,由于历史原因,目前仅在 Win32 中使用(当 Windows 95 出现时,UTF-16 是固定长度的)
2赞 8/27/2019
@VladislavToncharov UTF-16 从来都不是固定长度的编码。您将其与 UCS-2 混淆了。
0赞 Radvylf Programs 10/17/2020
@Kotauskas Javascript 仍然使用 UTF-16 来做几乎所有事情

答:

423赞 Adam Rosenfield 1/31/2009 #1

总之:

  • 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-16UTF-32

评论

70赞 Adam Rosenfield 8/4/2009
@spurrymoses:我严格指的是数据字节占用的空间量。UTF-8 每个亚洲字符需要 3 个字节,而 UTF-16 每个亚洲字符只需要 2 个字节。这真的不是一个大问题,因为与程序内存中存储的平均文本量相比,现在计算机拥有大量内存。
14赞 vine'th 11/14/2011
UTF-32 不再很少使用......在 OSX 和 Linux 上,默认为 4 个字节。GCC 有一个选项,可以将大小减小到 2 个字节,但会破坏与 std 库的二进制兼容性。wchar_t-fshort-wchar
9赞 Ustaman Sangat 12/16/2011
@PandaWood ofcource UTF-8 可以编码任何字符!但是,您是否将内存要求与 UTF-16 的内存要求进行了比较?你似乎错过了重点!
17赞 Paul Gregory 1/23/2013
如果有人说 UTF-8 在所有编码格式(包括那些无法编码 Unicode 的格式)的上下文中“不太适合亚洲文本”,他们当然是错误的。但这不是背景。内存需求的背景来自这样一个事实,即问题(和答案)正在比较 UTF-8、UTF-16 和 UTF-32,它们都将对亚洲文本进行编码,但使用不同的内存/存储量。因此,它们的相对优点自然完全取决于内存需求。“不太好” != “不好”。
8赞 Adam Rosenfield 10/19/2013
@McGafter:嗯,当然有。如果你想要可信度,请直接进入 Unicode Consortium 的马嘴。有关UTF-*编码的描述,请参见第2.5章。但是,为了获得对编码的简单、高层次的理解,我发现维基百科的文章是一个更平易近人的来源。
160赞 Quassnoi 1/31/2009 #2
  • UTF-8 是 1 到 4 个字节的变量。

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

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

评论

50赞 Urkle 2/25/2014
UTF8 实际上是 1 到 6 个字节。
8赞 5/14/2014
@Urkle技术上是正确的,因为映射 UTF32/LE/BE 的全范围包括 U-00200000 - U-7FFFFFFF,即使 Unicode v6.3 以 U-0010FFFF 结尾(含)。以下是如何 enc/dec 5 和 6 字节 utf8 的一个很好的细分: lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html
4赞 n611x007 6/6/2014
用相关的参考、零件及其来源来支持这些?
32赞 rdb 9/20/2015
@Urkle 不可以,UTF-8 不能是 5 或 6 个字节。Unicode 码位限制为 21 位,将 UTF-8 限制为 4 个字节。(当然,您可以扩展 UTF-8 的原理来编码任意大整数,但它不会是 Unicode。请参阅 RFC 3629。
18赞 Adam Calvet Bohl 1/20/2017
引用维基百科:2003 年 11 月,UTF-8 受到 RFC 3629 的限制,以匹配 UTF-16 字符编码的约束:明确禁止与高低代理项字符对应的码位删除超过 3% 的三字节序列,并以 U+10FFFF 结尾删除超过 48% 的四字节序列以及所有五字节和六字节序列。
502赞 AnthonyWJones 1/31/2009 #3

当 ASCII 字符表示文本块中的大多数字符时,UTF-8 具有优势,因为 UTF-8 将这些字符编码为 8 位(如 ASCII)。它还具有优势,因为仅包含 ASCII 字符的 UTF-8 文件具有与 ASCII 文件相同的编码。

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

UTF-32 将在 4 个字节中涵盖所有可能的字符。这使得它非常臃肿。我想不出使用它有什么好处。

评论

220赞 richq 1/31/2009
UTF-32 的优点:您不需要将存储的数据解码为 32 位 Unicode 码位,例如逐个字符处理。代码点已经在您的数组/向量/字符串中可用。
39赞 Paul McMillan 9/30/2009
如果(天堂帮助你)你必须重新实现轮子,也更容易解析。
40赞 Tim Čas 12/31/2011
好吧,UTF-8 在网络传输方面具有优势 - 无需担心字节序,因为您一次传输一个字节(而不是 4 个字节)的数据。
40赞 hamstergene 11/14/2012
@richq 不能在 UTF-32 中逐个字符处理,因为代码点并不总是与字符相对应。
11赞 Wes 6/7/2015
UTF-32 的优势:与 UTF-8 等效项相比,字符串操作可能更快
2赞 Paul W Homer 1/31/2009 #4

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

然而,字体、编码和东西都非常复杂(不必要?),所以需要一个大链接来填写更多细节:

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

不要指望能理解这一切,但如果你不想以后出现问题,那么值得尽可能多地学习,尽早(或者只是让别人为你解决)。

保罗。

评论

0赞 robotik 2/28/2020
或者只是使用 UTF-8 作为默认值,因为它已成为事实上的标准,并找出新系统是否支持它。 如果没有,您可以回到这篇文章。
0赞 Uncle Iroh 9/2/2021
@paul-w-homer 您的链接已损坏。
107赞 jalf 1/31/2009 #5

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 略有不同,但它们通常将 UTF-8 用于符合 Unicode 的所有内容。

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

评论

17赞 tchrist 3/7/2012
说Unicode为每个图形符号分配一个唯一的整数是不准确的。它为每个码位分配了这样的代码,但有些码位是不可见的控制字符,而有些图形符号需要多个码位来表示。
21赞 jalf 3/7/2012
@tchrist:是的,这是不准确的。问题是,要准确地解释Unicode,你需要写几千页。我希望能理解基本概念来解释编码之间的区别
0赞 Justin Ohms 7/9/2016
@jalf哈哈,所以基本上要解释Unicode,你必须编写Unicode核心规范
2赞 z33k 8/19/2020
迄今为止最好的答案
2赞 CDahn 2/1/2022
请注意,UTF-32 的描述不正确。每个字符的宽度不是 4 个字节。每个码位宽 4 个字节,有些字符可能需要多个码位。计算字符串长度不仅仅是字节数除以 4,您必须遍历整个字符串并解码每个代码点才能解析这些集群。
6赞 mghie 1/31/2009 #6

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

但是对于存储和交换数据,如果您可以选择,我总是使用 UTF-8。如果您主要拥有 ASCII 数据,这将为您提供最少的数据传输量,同时仍然能够对所有内容进行编码。优化最少的 I/O 是现代机器的必经之路。

评论

1赞 IInspectable 9/3/2018
可以说,比空间要求更重要的是,UTF-8 不受字节序的影响。UTF-16 和 UTF-32 将不可避免地要处理字节序问题,其中 UTF-8 只是一个八位字节流。
15赞 vartec 1/31/2009 #7

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

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

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

在这三者中,UTF-8显然是传播最广泛的。

评论

0赞 Morfidon 9/8/2017
为什么我要在开发网站时计算字符串的长度?在 Web 开发中选择 UTF-8/UTF-16 有什么优势吗?
1赞 8/27/2019
“优点是你可以很容易地计算出字符串的长度” 如果你用代码点的 # 来定义长度,那么是的,你可以将字节长度除以 4 就可以用 UTF-32 得到它。然而,这不是一个非常有用的定义:它可能与字符数无关。此外,规范化可能会更改字符串中的代码点数。例如,法语单词“été”可以用至少 4 种不同的方式编码,具有 3 个不同的代码点长度。
1赞 DexterHaxxor 6/5/2020
UTF-16 可能比 UTF-8 更快,同时也不会像 UTF-32 那样浪费内存。
0赞 Radvylf Programs 9/9/2021
@MichalŠtein 但它也给你带来了两全其美的最坏情况;它比 UTF-8 占用了更多的 ASCII 空间,但它也存在所有相同的问题,因为每个字符有多个代码点(除了潜在的字节序问题)。
15赞 Farid Movsumov 1/8/2013 #8

我做了一些测试来比较 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

评论

3赞 danilo 10/14/2020
一个短字符串并不意味着什么,只有一条记录就更少了,时差可能是由于其他因素造成的,Mysql本身的机制,如果要做一个可靠的测试,至少需要使用10000条记录,一个200个字符的字符串,而且需要是一组测试, 在某些情况下,至少大约 3 个,所以它会隔离编码因子
57赞 rook 5/15/2013 #9

Unicode是一个标准,关于UTF-x,你可以把它看作是一些实际目的的技术实现:

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

评论

0赞 tuxayo 6/21/2018
“主流语言”在世界很多地方都不是主流^^
3赞 tuxayo 6/21/2018
UTF-16 实际上针对非 ASCII 字符进行了大小优化。因为这真的取决于它将使用哪种语言。
0赞 rook 6/22/2018
@tuxayo完全同意,值得注意的是世界亚洲部分的汉字和汉字字符集。
0赞 DexterHaxxor 6/5/2020
应该是最好的答案。这太正确了,不能埋在这里。
2赞 qwr 5/13/2021
UTF-8 可能比所有这些都快,只是因为开发人员花了最多的精力来优化它
23赞 Jeff Adamson 3/6/2015 #10

UTF-8 格式

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

UTF-16 格式

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

UTF-32 格式

  • 每个字符是 4 个字节
  • 必须使用已知字节顺序或读取字节顺序标记 (BOM) 进行解析

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

UTF-32 最适合通过字符偏移到字节数组中进行随机访问。

评论

0赞 Koray Tugay 7/9/2016
UTF-8 中的“自同步”是如何工作的?你能举出 1 字节和 2 字节字符的例子吗?
2赞 Chris 8/2/2017
@KorayTugay 在较长的字符中从不使用有效的较短字节字符串。例如,ASCII 在 0-127 范围内,这意味着所有单字节字符的格式都是二进制的。所有双字节字符都以第二个字节开头。因此,假设一个双字节字符的第一个字符丢失了。一旦你看到没有前一个字节,你就可以确定一个字节丢失或损坏,并丢弃该字符(或从服务器或其他任何位置重新请求它),然后继续前进,直到你再次看到有效的第一个字节。0xxxxxxx110xxxxx10xxxxxx10xxxxxx110xxxxxx
1赞 Clearer 11/26/2017
如果你有一个字符的偏移量,你就有该字符的偏移量 -- UTF8、UTF16 或 UTF32 在这种情况下将同样工作;也就是说,它们都同样擅长通过字符偏移到字节数组中随机访问。utf32 比 utf8 更擅长计算字符的想法也是完全错误的。一个代码点(它与字符不同,又不等同于字素......叹息),在 utf32 中为 32 位宽,在 utf8 中为 8 到 32 位,但一个字符可以跨越多个代码点,这破坏了人们声称 utf32 相对于 utf8 的主要优势。
0赞 Radvylf Programs 9/9/2021
@Clearer 但是,您需要多久使用一次字符/字素,而不仅仅是代码点?我曾参与过许多涉及繁重字符串操作的项目,能够在 O(1) 中对代码点进行切片/索引确实非常有帮助。
0赞 Clearer 9/27/2021
@RedwolfPrograms 今天我没有,但我曾经从事语言分析工作,这非常重要。
-2赞 killjoy 5/21/2015 #11

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

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

一个常见的误解 - 后缀数字并不表示其能力。它们都支持完整的 Unicode,只是 UTF-8 可以用一个字节处理 ASCII,因此对 CPU 和互联网的效率更高/更不易损坏。

一些好读物:http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.htmlhttp://utf8everywhere.org

评论

0赞 IInspectable 9/3/2018
我不确定,为什么你建议使用 UTF-16 或 UTF-32 来支持非英语文本。UTF-8 可以很好地处理这个问题。英文文本中也有非 ASCII 字符。就像一个零宽度的非连接器。或者一个 em 破折号。恐怕,这个答案并没有增加多少价值。
0赞 Ṃųỻịgǻňạcểơửṩ 12/6/2019
这个问题很容易被否决,因为即使大多数字符是 UTF-8 中的 3 字节字符,UTF-8 仍然在 HTML 文件中常用,
0赞 robotik 2/28/2020
@IInspectable支持不是最好的措辞,促进或更好的支持会更准确
0赞 DexterHaxxor 6/5/2020
发送像 utf8everywhere.org 这样的页面不是我在 SO 答案中会做的事情。
47赞 Maroun 2/4/2016 #12

我试图在我的博文中给出一个简单的解释。

UTF-32 格式

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

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 个字节。它看起来像:

00000000 01000001

UTF-8 格式

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

最后,我们可以用与使用 ASCII 编码系统相同的方式表示“A”:

01001101

一个小例子,UTF-16 实际上比 UTF-8 更好:

考虑中文字母“語”——它的 UTF-8 编码是:

11101000 10101010 10011110

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

10001010 10011110

为了了解表示形式及其解释方式,请访问原始帖子。

评论

0赞 Smart Manoj 9/16/2020
stackoverflow.com/questions/3864842/....
0赞 Arik Jordan Graham 1/6/2022
计算机如何不“删除”包含大量零的 UTF-32 编码数字?比如表示“A”将包含 26-27 个零......
13赞 samanthaj 1/7/2021 #13

我很惊讶这个问题已经有 11 年的历史了,而且没有一个答案提到 utf-1 的 #8 优势。

UTF-8 通常适用于无法识别 UTF-8 的程序。这在一定程度上是它的设计目的。其他答案提到前 128 个代码点与 ASCII 相同。所有其他代码点都由设置了高位(值从 128 到 255)的 8 位值生成,因此从非 unicode 感知程序的 POV 中,它只会将字符串视为带有一些额外字符的 ASCII。

举个例子,假设你编写了一个程序来添加行号,可以有效地做到这一点(为了简单起见,让我们假设行尾只是 ASCII 13)

// pseudo code

function readLine
  if end of file
     return null
  read bytes (8bit values) into string until you hit 13 or end or file
  return string

function main
  lineNo = 1
  do {
    s = readLine
    if (s == null) break;
    print lineNo++, s
  }  

将 utf-8 文件传递给此程序将继续工作。同样,在制表符、逗号上拆分、解析 ASCII 引号或其他只有 ASCII 值很重要的解析都仅适用于 utf-8,因为 utf-8 中没有 ASCII 值,除非它们实际上是这些 ASCII 值

其他一些答案或评论提到 utf-32 的优点是您可以单独处理每个代码点。例如,这建议您可以采用像“ABCDEFGHI”这样的字符串,并在每 3 个代码点将其拆分

ABC
DEF
GHI

这是错误的。许多代码点会影响其他代码点。例如,颜色选择器代码点允许您在 👨🏻 🦳👨🏿 🦳👨🏼 🦳👨🏾 🦳👨🏽 🦳 .如果你在任何任意代码点拆分,你就会破坏它们。

另一个例子是双向码位。以下段落没有倒过来。它前面是0x202E代码点

  • ‮This line is not typed backward it is only displayed backward

所以不,utf-32 不会让您随意操作 unicode 字符串而不考虑它们的含义。它可以让您在没有额外代码的情况下查看每个代码点。

仅供参考,utf-8 的设计使得查看任何单个字节,您都可以找出当前代码点或下一个代码点的开始。

如果在 utf-8 数据中采用任意字节。如果它< 128,则它本身就是正确的代码点。如果它是 >= 128 且< 192(前 2 位是 10),那么要找到代码点的开头,您需要查看前面的字节,直到找到值为 >= 192 的字节(前 2 位是 11)。在那个字节处,你已经找到了代码点的起点。该字节对构成代码点的后续字节数进行编码。

如果要查找下一个代码点,只需扫描直到字节< 128 或 >= 192,这就是下一个代码点的开始。

字节数 第一个代码点 最后一个代码点 字节 1 字节 2 字节 3 字节 4
1 U+0000 U+007F 0xxxxxxx
2 U+0080 U+07FF 110xxxxx 10xxxxxx
3 U+0800 U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
4 U+10000 U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

代码点的位在哪里。将字节中的 xxxx 位连接起来以获取代码点xxxxxx

评论

0赞 whY 9/19/2023
另一个设计特点:UTF-8 无感知代码可以按升序对 UTF-8 字符串进行正确排序(无论这多么有用)
1赞 Keith Downes 2/6/2022 #14

看完答案后,UTF-32 需要一些爱。

C#:

Data1 = RandomNumberGenerator.GetBytes(500_000_000);

sw = Stopwatch.StartNew();
int l = Encoding.UTF8.GetString(Data1).Length;
sw.Stop();
Console.WriteLine($"UTF-8: Elapsed - {sw.ElapsedMilliseconds * .001:0.000s}   Size - {l:###,###,###}");

sw = Stopwatch.StartNew();
l = Encoding.Unicode.GetString(Data1).Length;
sw.Stop();
Console.WriteLine($"Unicode: Elapsed - {sw.ElapsedMilliseconds * .001:0.000s}   Size - {l:###,###,###}");

sw = Stopwatch.StartNew();
l = Encoding.UTF32.GetString(Data1).Length;
sw.Stop();
Console.WriteLine($"UTF-32: Elapsed - {sw.ElapsedMilliseconds * .001:0.000s}   Size - {l:###,###,###}");

sw = Stopwatch.StartNew();
l = Encoding.ASCII.GetString(Data1).Length;
sw.Stop();
Console.WriteLine($"ASCII: Elapsed - {sw.ElapsedMilliseconds * .001:0.000s}   Size - {l:###,###,###}");

UTF-8 -- 已用 9.939 秒 - 大小 473,752,800

Unicode -- 经过 0.853s - 大小 250,000,000

UTF-32 -- 经过 3.143 秒 - 大小 125,030,570

ASCII -- 经过 2.362 秒 - 大小 500,000,000

UTF-32 -- 麦克风丢弃