utf-8、utf-16和utf-32有什么区别?
我知道它们都将存储Unicode,并且每个都使用不同的字节数来表示一个字符。选择一个比另一个有好处吗?
- 如果您对unicode如何工作感兴趣,请观看此视频youtube.com/watch?V= MijMeOH9LT4
- 这段视频关注的是UTF-8,是的,它很好地解释了可变长度编码是如何工作的,并且主要与只读或写固定长度ASCII的计算机兼容。Unicode的家伙在设计UTF-8编码时很聪明。
- 我已经创建了一个用于转换和比较的在线工具。
在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-32优点:您不需要将存储的数据解码为32位Unicode码位,例如逐字符处理。代码点已经在数组/向量/字符串中可用。
- @RQ:你说得很对,亚当也这么说。但是,我见过的大多数逐字符处理都是使用16位短整数,而不是32位整数的向量。就原始速度而言,某些操作将更快地使用32位。
- 如果(天堂帮助你),你必须重新实现轮子,那么解析起来也更容易。
- utf32优点:当通过网络传输时,特别是在UDP中,最好知道在需要所有字符的情况下,4字节总是一个字符。
- 好吧,UTF-8在网络传输中有一个优势——无需担心endianness,因为您一次传输一个字节的数据(而不是4)。
- @RichQ不能在utf-32中逐字符处理,因为代码点并不总是对应于字符。
- -1这仅仅是因为UTF-32有两个优点,即使它们不够重要,以至于许多项目都想选择它。我知道的唯一使用它的项目是字处理器abiword。
- @Hippietrail能说出utf-32的一些优点吗?其他评论中没有提到这些优点。
- @NAXA:其他评论已经提到了UTF-32的优点。Anthonywjones说:"我想不出使用它有什么好处。"
- 我个人总是使用UTF-8,除了我使用UTF-16的Windows API代码。几年前,当我参与AbiWord时,他们选择在内部使用UTF-32,这仍然是我知道的唯一一个这样做的项目。我不知道他们是否坚持下去了。仅仅因为有些人混淆了"字符"和"代码点",并不意味着知道代码点都是固定大小没有好处。
- UTF-32的优点:字符串操作可能比UTF-8的同类操作更快。
- @韦斯:我对此表示怀疑;大多数字符串处理都不是基于每个字符(子字符串搜索在ASCII、UTF-8或任意字节数组上同样有效,不管它们[可能]编码的字符数据如何)。如果是,那么utf-32就不够了(即使在完全规范化的utf-32中,每个字符也可以有多个单位!)。如果有任何问题,它会使复制速度变慢,因为(大致)复制的数据是4倍。
- @韦斯:我发现了一个很好的来源:图5(官方!)文件。请注意,即使是规范化的字符也是多个代码点(因此,即使是UTF-32)。
- "提姆?"比如说代码点,而不是笔迹。在utf-8中,按偏移量定位代码点是一项非常密集的操作,因为它需要完全迭代,其中"跳转"为2->4字节,而utf-32具有实际的随机访问权限。因此,子串操作更快。相反,正如您所说,在两种编码中定位图形都需要完全遍历,但在UTF-32中,只需要更少的跳转。
- @韦斯:但是什么子串操作需要这个呢?例如,在utf-8上查找子串和在utf-32上查找子串的效果一样好(您只需查找uint8s/uint32s的特定序列)。在这两种情况下,返回的索引都可以直接用于(例如)到字符串末尾的切片。
- 也可以,但这不是随机访问。例如,仅仅知道字符串的长度(在代码点中)就需要对字节数组进行完全遍历,而对于utf-32,它只是sizeof(代码点)
- 这句话有点令人困惑:"UTF-8将所有字符编码为8位"。
- 语句"utf-8将所有字符编码为8位"是错误的。它不会将"所有"字符编码为8位。它使用可变长度编码,这是8位的倍数。所以字符可以取8,16,24,最多32位!
- UTF8的另一个优点是不需要复制API。就像那些讨厌的Windows w版本的API。他们为什么不采用UTF8?
- 描述utf32随机访问能力的另一种方法是说字符串切片是utf32中的o(1)和utf8中的o(n),即使在最好的情况下也是如此。
- utf-32不仅对字符串操作更有效(它支持随机访问;说得够多了!)但是由于它是一个固定大小的数组,所以操作起来也比较简单(我敢说你在C中使用utf-8…)
- @纳瓦兹注意到,有些位用于标识字符的大小,因此您不能将整个8或16等位用于您的字符。
简而言之:
- 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-16工作的原因是U+D800–U+DFFF在BMP中作为代理项对的间隙保留。聪明。
- 型@亚当:很好的总结。+1个
- 型"utf8对中文文本不太好"是怎么回事?这是错误的。例如,UTF-8非常适合日语。我运行一个日文网站,所有内容都用UTF8编码,一切正常。UTF-8可以编码任何Unicode字符。
- 型@SpuryMoses:我指的是数据字节占用的空间量。UTF-8需要每个亚洲字符3个字节,而UTF-16只需要每个亚洲字符2个字节。这真的不是一个大问题,因为与程序内存中平均存储的文本量相比,计算机现在有大量的内存。
- 型UTF-32已经不再很少使用了…在OSX和Linux上,wchar_t默认为4字节。gcc有一个选项-fshort-wchar,它将大小减少到2个字节,但破坏了与std libs的二进制兼容性。
- 型@Pandawood of Cource UTF-8可以对任何字符进行编码!但是,您是否比较了UTF-16的内存需求?你好像错过了重点!
- 型@是的,如果这个答案仅限于内存需求,那么我就错过了这一点。然而,这一点从未在答案中提出(问题也不需要这样做)。看来,我错过了一个从未有过的观点,但不知怎的,你甚至可以不说就看得见。如果有人说UTF-8"对亚洲文本不太好"——在不限制其内存需求的情况下,这是错误的。
- 型如果有人说UTF-8在所有编码格式(包括那些不能编码Unicode的格式)的上下文中"不太适合亚洲文本",那么他们当然是错的。但这不是背景。内存需求的上下文来自这样一个事实:问题(和答案)正在比较utf-8、utf-16和utf-32,它们都对亚洲文本进行编码,但使用的内存/存储量不同。因此,它们的相对优势自然完全是在记忆需求的背景下产生的。"不是很好"!="不好"。
- 型@藤蔓:我所看到的,wchar_t并没有获得太多的人气。事实上,它在Windows上的宽度为16位,在*nix上的宽度为32位,这可能是它缺乏接受度的原因之一。在*nix中,大多数项目都避开wchar_t,只使用带有utf-8的char。
- 型维基百科评论说,在实际使用中,由于文本中仍然使用了大量的空格或英语单词,所以在使用非英语字符时,utf-8比utf-16更小。
- 型没有比维基百科更值得信赖的参考资料了吗?(不是说stackoverflow在这方面更好…)
- 型@麦格雷特:当然有。如果你想要值得信赖的话,直接去unicode联盟的马口吧。有关utf-*编码的描述,请参见第2.5章。但是为了获得对编码的简单、高层次的理解,我发现维基百科的文章是一个更容易接近的来源。
- 型@Pandawood网页包含大量不属于正文的ASCII字符,因此无论您使用什么语言,UTF-8都是不错的选择。
- 型虽然对于大多数亚洲字符来说,UTF-8需要3个字节,而对于UTF-16则需要2个字节(一些常用的中文字符最终出现在多语言平面上,在UTF-8和UTF-16中,它们都需要4个字节),但实际上,这并没有多大的区别,因为真实文档中常常混合了大量的ASCII字符。请参阅utf8everywhere.org/asian了解一个实际文档的并排大小比较:与utf-16相比,utf-8编码日语HTML页(维基百科关于日本的文章,日语)实际减少了50%的字节。
UTF-8是变量1到4字节。
UTF-16是变量2或4字节。
UTF-32固定为4个字节。
- 型utf8实际上是1到6个字节。
- @Urkle在技术上是正确的,因为映射整个utf32/le/be范围包括U-00200000-U-7fffffff,即使Unicode V6.3以U-0010ffff结尾(包括U-0010ffff)。下面是如何ENC/DEC 5和6字节的utf8:lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html的详细说明。
- 用相关的参考零件及其来源备份这些零件?
- @urle no,utf-8不能是5或6字节。Unicode码位限制为21位,这将UTF-8限制为4字节。(当然,您可以扩展utf-8的原则来编码任意的大整数,但它不是Unicode。)参见RFC3629。
- 你们为什么要改变尺寸?UTF-8 1-4字节..然后1-6。那为什么还有其他UTF呢?
- 引用维基百科:2003年11月,为了匹配UTF-16字符编码的约束,UTF-8受到了RFC 3629的限制:明确禁止与高、低代理字符相对应的代码点删除了超过3%的三字节序列,以u+10ffff结尾的代码点删除了超过48%的四字节序列和所有的五字节和六字节序列。
- 将来是否可以扩展标准以允许其中任何一个使用5字节,或者以某种技术方式将其限制为4字节?
- @aaronfranke:第一个字节可以定义多达7个连续字节,因此从技术上讲,每个序列可以扩展到8个字节(36个有效负载位~680亿码位)。
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为每个图形符号分配了一个唯一的整数。它为每个代码点分配这样的代码,但有些代码点是不可见的控制字符,有些图形符号需要多个代码点来表示。
- @是的,这是不准确的。问题是,要准确解释Unicode,需要编写数千页。我希望把基本概念解释清楚,以解释编码之间的区别。
- @JALF LOL是正确的,所以基本上要解释Unicode,您必须编写Unicode核心规范。
Unicode是一种标准,关于UTF-X,您可以将其视为一些实际用途的技术实现:
- UTF-8-"大小优化":最适合基于拉丁字符的数据(或ASCII),每个字符只需要1个字节,但大小会相应地增加符号的多样性(在最坏的情况下,每个字符最多可以增加6个字节)
- UTF-16-"平衡":每个字符至少需要2个字节,这足以满足现有的主流语言集的需要,并且具有固定的大小,以便于字符处理(但大小仍然是可变的,每个字符最多可以增长4个字节)
- utf-32-"性能":允许使用简单的算法作为固定大小字符(4字节)的结果,但内存不足
- «;主流语言&187;不是世界许多地方的主流语言^^
- UTF-16实际上是针对非ASCII字符进行大小优化的。因为它实际上取决于将使用哪种语言。
- @陀沙洋完全同意,值得注意的是,世界上亚洲地区的汉字和汉字集。
我试着在博客上简单解释一下。
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个字节。看起来像是:
UTF-8
你猜对了……在UTF-8中,代码点可以用32、16、24或8位来表示,作为UTF-16系统,这个系统也是可变长度编码系统。
最后,我们可以用同样的方式表示"A",我们使用ASCII编码系统表示它:
一个小例子,其中utf-16实际上比utf-8好:
考虑中文字母"語"-其UTF-8编码为:
1
| 11101000 10101010 10011110 |
虽然它的UTF-16编码更短:
为了理解陈述及其解释方式,请访问原始帖子。
UTF-8
- 没有字节顺序的概念
- 每个字符使用1到4个字节
- ASCII是编码的兼容子集
- 完全自同步,例如流中任何位置的丢弃字节最多会损坏一个字符
- 几乎所有的欧洲语言都是以两个字节或更少的字符编码的。
UTF 16
- 必须用已知的字节顺序分析或读取字节顺序标记(BOM)
- 每个字符使用2或4个字节
UTF 32
- 每个字符4个字节
- 必须用已知的字节顺序分析或读取字节顺序标记(BOM)
除非大部分字符来自CJK(中文、日文和韩文)字符空间,否则UTF-8将是最节省空间的字符。
UTF-32最适合按字符偏移量随机访问字节数组。
- 在UTF-8中,"自同步"是如何工作的?你能举出1字节和2字节字符的例子吗?
- @Koraytugay有效的较短字节字符串从不用于较长的字符。例如,ASCII在0-127范围内,这意味着所有单字节字符的形式都是二进制的0xxxxxxx。所有两个字节的字符都以110xxxxx开头,第二个字节以10xxxxxx开头。所以假设一个双字节字符的第一个字符丢失了。当您看到没有前面的110xxxxxx的10xxxxxx时,您可以确定某个字节丢失或损坏,并丢弃该字符(或从服务器重新请求该字符或其他字符),然后继续前进,直到再次看到有效的第一个字节。
- 如果对字符有偏移量,则对该字符有偏移量——在这种情况下,utf8、utf16或utf32的工作原理是相同的;也就是说,它们在按字符偏移量随机访问字节数组时都同样擅长。认为utf32比utf8更擅长计算字符的想法也是完全错误的。一个代码点(它与字符不同,字符又不同于笔迹)。sigh),在utf32中是32位宽,在utf8中是8到32位之间,但是一个字符可能跨越多个码点,这破坏了人们声称utf32比utf8的主要优势。
我做了一些测试来比较MySQL中utf-8和utf-16的数据库性能。
更新速度UTF-8
UTF 16
插入速度
删除速度
在UTF-32中,所有字符都用32位编码。其优点是可以轻松计算字符串的长度。缺点是,对于每个ASCII字符,您会浪费额外的三个字节。
在UTF-8字符中,长度可变,ASCII字符用一个字节(8位)编码,大多数西方特殊字符用两个字节或三个字节(例如欧元是三个字节)编码,更多的外来字符可以用四个字节。明显的缺点是,不能预先计算字符串的长度。但与UTF-32相比,编写拉丁(英语)字母文本所需的字节要少得多。
UTF-16也是可变长度的。字符可以用两个字节或四个字节编码。我真的不明白这一点。它的缺点是长度可变,但没有像UTF-8那样节省空间。
显然,在这三种技术中,UTF-8的传播最为广泛。
- 为什么我要在开发网站时计算字符串的长度?在Web开发中选择utf-8/utf-16有什么好处吗?
根据开发环境的不同,您甚至可能无法选择在内部使用什么编码字符串数据类型。
但是对于存储和交换数据,如果您有选择的话,我总是使用UTF-8。如果您有大部分的ASCII数据,这将为您提供最少的数据传输量,同时仍然能够对所有数据进行编码。优化最少的I/O是现代机器的发展方向。
- 可以说,比空间需求更重要的是事实上,UTF-8不受endianness的影响。UTF-16和UTF-32将不可避免地要处理无端性问题,其中UTF-8只是一个八位字节流。
如前所述,差异主要是基础变量的大小,在每种情况下,基础变量的大小都会变大,以允许更多的字符被表示。
然而,字体、编码和事情都非常复杂(不必要吗?),因此需要一个大链接来更详细地填写:
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
- 我不确定,为什么你建议使用UTF-16或UTF-32来支持非英语文本。UTF-8可以很好地处理这个问题。英语文本中也有非ASCII字符。像一个零宽度的非连接者。或者是一个破折号。恐怕这个答案没什么价值。