Unicode和UTF-8有什么区别?

238

请考虑以下内容:

图片描述

unicode=utf16”这种说法是否正确?

很多人认为Unicode是一个标准,而不是一种编码,但是大多数编辑器实际上支持以Unicode编码的方式保存。


5
不行,因为大多数文本编辑器都是这样做的。 - ollydbg
1
@olly:你在使用Windows吗?试试下载Notepad++ - Matt Ball
6
我正在使用EditPlus,一直都很好用,我不想换其他编辑器。 - ollydbg
请参见https://dev59.com/HXRB5IYBdhLWcg3wLUq3。 - tripleee
9个回答

663

在他的文章"UTF-8和Unicode之间的区别?"中,Rasmus指出:

如果有人问你:“UTF-8和Unicode有什么区别?”你能自信地回答一个简短而精确的答案吗?在这个国际化的时代,每个开发者都应该能够做到。我怀疑我们中许多人并没有像我们应该那样理解这些概念。如果你觉得你属于这个群体,那么你应该阅读这篇关于字符集和编码的超短介绍。

实际上,将UTF-8和Unicode进行比较就像比较苹果和橙子:

UTF-8是一种编码 - Unicode是一个字符集

一个字符集是具有唯一编号(这些编号有时被称为“代码点”)的一系列字符列表。例如,在Unicode字符集中,A的编号为41。

另一方面,编码是一种算法,它将一系列数字转换为二进制形式,以便可以存储在磁盘上。例如,UTF-8会将数字序列1、2、3、4转换成这样:

00000001 00000010 00000011 00000100 

我们的数据现在已经被转换成二进制,可以保存到磁盘上。

一切准备就绪

假设一个应用程序从磁盘中读取以下内容:

1101000 1100101 1101100 1101100 1101111 

这个应用程序知道这些数据表示使用UTF-8编码的Unicode字符串,并且必须将其显示为文本给用户。第一步是将二进制数据转换为数字。该应用程序使用UTF-8算法解码数据。在此情况下,解码器返回以下内容:

104 101 108 108 111 

由于应用程序知道这是一个Unicode字符串,因此可以假定每个数字代表一个字符。我们使用Unicode字符集将每个数字转换为相应的字符。最终得到的字符串是“hello”。

结论

因此,当有人问你“UTF-8和Unicode之间有什么区别?”时,你现在可以自信地给出简短而精确的答案:

UTF-8(Unicode转换格式)和Unicode不能进行比较。 UTF-8是一种用于将数字转换为二进制数据的编码。 Unicode是一种用于将字符转换为数字的字符集。


9
这个说法是完全正确的,回答了标题中提出的问题。但是它并没有回答实际的问题,因为该问题基于一种错误的理解,即将“Unicode”用来指代“UTF-16”。 - Mark Ransom
5
抱歉,但我完全不理解,“它使用utf8算法解码二进制”是什么意思?二进制就是二进制,只需要进行数学运算才能将其转换回十进制。如果您告诉我十进制(41)在Unicode中表示为A,那么我不需要其他任何信息来将其存储为二进制并获取它。 - sliders_alpha
5
UTF-8编码根据每个字符动态分配位数,而Unicode为每个字符使用32位。本答案的示例仅使用7位ASCII字符,这就是为什么它易于理解并满足大多数读者的原因,但UTF-8并不那么容易。如果您还能提供一些多字节示例,那就更好了。 - John Smith
4
UTF-8不仅仅是一种编码方式,它也是一个字符集。更准确地说,UTF-8使用Unicode作为其字符集。我的意思是,你不能将它用作另一个字符集的编码方式。 - yannick1976
3
“二进制就是二进制,只需要数学计算就能将其转换回十进制”这种说法是错误的,非常错误。我们在这里不是谈论数字进位制,而是谈论编码方案。UTF-8并不仅仅将十进制数转换为二进制,它比那更加复杂。这个答案中提供的例子很糟糕,因为它使用了数字1、2、3和4,这些数字刚好恰好可以编码成它们的二进制表示形式,但这并不一定正确。特别是对于使用了非平凡位偏移的UTF-8编码。我建议您阅读有关UTF-8编码算法的维基百科文章。 - JeneralJames
显示剩余6条评论

179
大多数编辑器实际上支持“Unicode”编码的保存。
这是Windows误导用户的不幸之举。
因为Windows在内部使用UTF-16LE编码作为Unicode字符串的存储格式,因此它认为这是Unicode文本的自然编码。在Windows世界中,有ANSI字符串(当前机器上的系统代码页,完全不可移植)和Unicode字符串(以UTF-16LE内部存储)。
这都是在Unicode早期设计时制定的,在我们意识到UCS-2不够用,并且在UTF-8发明之前。这就是为什么Windows对UTF-8的支持非常差的原因。
这种误导性的命名方案成为了用户界面的一部分。一个使用Windows编码支持提供一系列编码的文本编辑器将自动并不恰当地将UTF-16LE描述为“Unicode”,并将UTF-16BE(如果提供)描述为“Unicode big-endian”。
(像Notepad++等自行处理编码的其他编辑器则没有这个问题。)
如果您对此感到更好,那么“ANSI”字符串也没有基于任何ANSI标准。

33

19

这里存在很多误解。Unicode不是一种编码,而Unicode标准主要是用于编码。

ISO 10646是你(可能)关心的国际字符集。它定义了一种命名字符集(例如,“Latin Capital Letter A”或“Greek small letter alpha”)和一组代码点之间的映射(为每个分配的数字 - 例如61十六进制和3B1十六进制分别对应;对于Unicode代码点,标准表示法将是U+0061和U+03B1)。

曾经,Unicode定义了自己的字符集,更像是ISO 10646的竞争者。它是一个16位字符集,但不是UTF-16;它被称为UCS-2。它采用了一种相当有争议的技术,试图将必需字符的数量最小化(汉字统一 - 基本上将相似的中文、日文和韩文字符视为相同字符)。

此后,Unicode联盟默认承认这种方法行不通,并主要集中于编码ISO 10646字符集的方式。主要方法是UTF-8、UTF-16和UCS-4(也称为UTF-32)。这些方法(除了UTF-8)还有LE(小端序)和BE(大端序)变体。

单独使用“Unicode”,几乎可以指任何上述方式(尽管我们可能可以排除它明确显示的其他方式,例如UTF-8)。在Windows上最常出现不加限定的“Unicode”,几乎肯定是指UTF-16。早期版本的Windows NT在UCS-2流行时采用了Unicode。在UCS-2被宣布过时后(大约在Win2k左右),它们切换到UTF-16,这是与UCS-2最相似的(事实上,在“基本多语言平面”中的字符包括大多数西欧语言的所有字符,两者完全相同)。


1
但是,微软为什么要将这个问题延续到 .NET 中呢?.NET 不是 Win2k 后的发明吗? - President James K. Polk

15

UTF-16和UTF-8都是Unicode的编码方式。它们是Unicode,其中一个不会比另一个Unicode。

不要让微软的历史遗物困扰你。


6

3

除了Trufa的评论之外,Unicode明确不是UTF-16。当他们最初研究Unicode时,有人猜测一个16位整数可能足以存储任何代码,但实践证明这并非如此。不过,UTF-16是Unicode的另一种有效编码,与8位和32位变体并列存在,我相信它是微软在NT派生操作系统中运行时内存中使用的编码。


1
那么对于Visual Studio来说, Unicode = UTF16 是正确的,对吗? - ollydbg
1
@ollydbg,UTF-16确实是Windows中Unicode的自然表示方式,但这并不意味着它们完全相同。 - Mark Ransom

2

让我们始终记住数据以字节为单位存储;Unicode是一个字符集,其中字符被映射到代码点(唯一的整数),我们需要某种方式将这些代码点数据转换为字节。这就是所谓的编码UTF-8派上用场的地方 - 简单易懂!


1

这很奇怪。Unicode是一个标准,而不是一种编码方式。由于可以指定字节序,我猜它实际上是UTF-16或者UTF-32。

这个菜单是从哪里提供的?


来自名为EditPlus的文本编辑器。 - ollydbg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接