我听到了许多人的不同意见 - 根据维基百科 UTF-8页面。
它们不是一个东西吗?有人能澄清一下吗?
对其他人所给出的答案进行补充:
我们有很多语言,其中包含许多计算机理想显示的字符。Unicode为每个字符分配一个唯一的数字或代码点。
计算机将这些数字处理为字节...在此跳过一些历史并忽略内存寻址问题,8位计算机将把8位字节视为最容易在硬件上表示的最大数值单位,16位计算机将将其扩展到两个字节,依此类推。
旧的字符编码(如ASCII)来自于(前)8位时代,并试图将当时计算机中占主导地位的语言即英语压缩成从0到127(7位)的数字。由于字母表中有26个字母,大小写形式都有,还有数字和标点符号,因此这种方法非常有效。 ASCII通过第8位来扩展其他非英语语言,但是由此扩展提供的额外128个数字/代码点将根据显示的语言映射到不同的字符。 ISO-8859标准是此映射的最常见形式; ISO-8859-1和ISO-8859-15(也称为ISO-Latin-1,latin1,是的,8859 ISO标准有两个不同的版本)。
但是当你想要表示来自多种语言的字符时,仅将所有可用字符塞到一个字节中就不够用了。
基本上有两种不同类型的编码方式:一种是通过添加更多位数来扩展值范围。这些编码的例子包括UCS2(2个字节= 16位)和UCS4(4个字节= 32位)。它们具有与ASCII和ISO-8859标准相同的固有问题,因为它们的值范围仍然受到限制,即使限制远高于原先的标准。
另一种编码类型使用可变长度的字节来表示字符,最常见的编码方式是UTF编码。所有UTF编码的工作方式基本相同:您选择一个单元大小,对于UTF-8是8位,对于UTF-16是16位,对于UTF-32是32位。标准然后定义了一些这些位作为标志:如果设置了它们,则序列中下一个单元应视为同一字符的一部分。如果没有设置,此单元完全表示一个字符。因此,最常见的(英文)字符在UTF-8中仅占用一个字节(在UTF-16中为两个字节,在UTF-32中为4个字节),但其他语言的字符可能占用六个或更多字节。
多字节编码(在上面的解释之后,我应该说是多单元编码)具有相对节省空间的优点,但缺点是像查找子字符串、比较等操作都必须先将字符解码为unicode代码点,然后才能执行这些操作(虽然有一些快捷方式)。1111110v 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv
- 这确实是6个字节。然而,6个字节是最大值,而不是该文章所混淆地声称的“六个或更多字节”。 - syntaxerrorA Chinese character: 汉
its Unicode value: U+6C49
convert 6C49 to binary: 01101100 01001001
Binary format of bytes in sequence
1st Byte 2nd Byte 3rd Byte 4th Byte Number of Free Bits Maximum Expressible Unicode Value
0xxxxxxx 7 007F hex (127)
110xxxxx 10xxxxxx (5+6)=11 07FF hex (2047)
1110xxxx 10xxxxxx 10xxxxxx (4+6+6)=16 FFFF hex (65535)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (3+6+6+6)=21 10FFFF hex (1,114,111)
Header Place holder Fill in our Binary Result
1110 xxxx 0110 11100110
10 xxxxxx 110001 10110001
10 xxxxxx 001001 10001001
11100110 10110001 10001001
A Chinese character: 汉
its Unicode value: U+6C49
convert 6C49 to binary: 01101100 01001001
encode 6C49 as UTF-8: 11100110 10110001 10001001
"Unicode"被不同的上下文以不同的方式使用。在我看来,它最正确的用法是作为一种编码字符集 - 即一个字符集和将字符映射为整数代码点的映射。
UTF-8是一种字符编码方式,用于将字节序列转换为字符序列以及反向转换。它覆盖了整个Unicode字符集。ASCII字符编码为每个字符一个字节,而其他字符则根据其精确的代码点采用更多的字节(对于所有当前定义的代码点,即U-0010FFFF以内的字符,最多需要4个字节;实际上,4个字节可以处理U-001FFFFF以内的字符)。
当"Unicode"作为字符编码的名称使用时(例如.NET Encoding.Unicode属性),它通常表示UTF-16,该编码将大部分常见字符编码为两个字节。某些平台(特别是.NET和Java)使用UTF-16作为其“本地”字符编码。如果您需要考虑无法用单个UTF-16值编码的字符(它们会被编码为"代理对"),这会导致混乱的问题 - 但是大多数开发人员从不关心这个,以我的经验来看。
Unicode的一些参考资料:
它们不是同一件事 - UTF-8 是一种特定的 Unicode 编码方式。
根据您的应用程序和所使用的数据,可以选择许多不同的编码方式。据我所知,最常见的有 UTF-8、UTF-16 和 UTF-32。
Unicode只定义了码点,即表示字符的数字。如何将这些码点存储在内存中取决于您使用的编码方式。 UTF-8是一种编码Unicode字符的方式,有许多其他方式。
http://www.wikiwand.com/en/UTF-8#/Description
- nightlytrails在UTF-8编码中,ASCII编码中存在的字符以与ASCII相同的方式进行编码,因此任何ASCII字符串自然也是一个有效的UTF-8字符串,表示相同的字符。
更高效:UTF-8中的文本字符串几乎总是比UTF-32或UTF-16中的相同字符串占用更少的空间,只有少数例外。
二进制排序:使用二进制排序对UTF-8字符串进行排序仍然会导致所有代码点按照数字顺序排序。
当一个代码点使用多个字节时,这些字节中没有一个(甚至是第一个字节)包含ASCII范围内的值,确保它们的任何部分都不会被误认为是ASCII字符。这是一个重要的安全特性,特别是在使用最初设计为8位编码的系统中使用UTF-8编码文本时。
可以轻松验证UTF-8以确保其为有效的UTF-8。其他8位或多字节编码的文本很少会因为UTF-8的特定结构而偶然验证为UTF-8。
随机访问:在UTF-8字符串的任何位置,可以确定该位置的字节是否是一个字符的第一个字节,以及找到下一个或当前字符的起始位置,而无需向前或向后扫描超过3个字节或知道我们从字符串的哪个位置开始读取。
Unicode 是一个标准,它定义了一个字符集 (UCS) 以及编码方案 (UTF) 来对该字符集进行编码。但一般情况下,Unicode 指的是字符集而不是标准。
请阅读 The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) 和 Unicode In 5 Minutes。
现有的答案已经解释了很多细节,但这里是一个非常简短的答案,带有最直接的解释和示例。
Unicode是将字符映射到代码点的标准。
每个字符都有一个唯一的代码点(识别号),它是像9731这样的数字。
UTF-8是代码点的编码之一。
为了将所有字符存储在磁盘上(在文件中),UTF-8将字符分成最多4个八位字节序列 - 字节。
UTF-8是多种编码(表示数据的方法)之一。例如,在Unicode中,(十进制)代码点9731代表雪人(☃
),在UTF-8中由3个字节表示:E2 98 83
这里是一个随机示例的排序列表。
在阅读了关于这个话题的众多帖子和文章之后,我得出了以下解释:
"Unicode"是一个巨大的表格,它有21位宽度,这21位提供了1,114,112个代码点/值/字段/位置来存储字符。
在这1,114,112个代码点中,有1,111,998个可以存储Unicode字符,因为有2048个代码点被保留为代理项,还有66个代码点被保留为非字符。因此,有1,111,998个代码点可以存储独特的字符、符号、表情等。
然而,截至目前,这1,114,112个代码点中只有144,697个被使用。这144,697个代码点包含了覆盖所有语言、符号、表情等的字符。
每个字符在“Unicode”中都被分配了一个特定的码点,也就是一个特定的值/Unicode编号。例如,字符“❤”使用了1,114,112个码点中的一个。它的值(即Unicode编号)是“U+2764”。这是一个由两个字节组成的十六进制码点,以二进制表示为00100111 01100100。但是为了表示这个码点,UTF-8编码使用了3个字节(24位),以二进制表示为11100010 10011101 10100100(不包括两个空格字符,每个字符使用1位,我只是为了可视化目的添加了它们,所以请忽略它们)。 Binary format of bytes in sequence:
1st Byte 2nd Byte 3rd Byte 4th Byte Number of Free Bits Maximum Expressible Unicode Value
0xxxxxxx 7 007F hex (127)
110xxxxx 10xxxxxx (5+6)=11 07FF hex (2047)
1110xxxx 10xxxxxx 10xxxxxx (4+6+6)=16 FFFF hex (65535)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (3+6+6+6)=21 10FFFF hex (1,114,111)
Header Place holder Fill in our Binary Result
1110 xxxx 0110 11100110
10 xxxxxx 110001 10110001
10 xxxxxx 001001 10001001
A Chinese character: 汉
its Unicode value: U+6C49
convert 6C49 to binary: 01101100 01001001
encode 6C49 as UTF-8: 11100110 10110001 10001001
UTF-8、UTF-16和UTF-32编码之间的主要区别在于它们在内存中表示一个字符所需的字节数:
UTF-8使用至少1个字节,但如果字符更大,则可以使用2、3或4个字节。UTF-8还与ASCII表兼容。
UTF-16使用至少2个字节。UTF-16不能使用3个字节,只能使用2个或4个字节。UTF-16与ASCII表不兼容。
UTF-32始终使用4个字节。
记住:UTF-8和UTF-16是可变长度编码,其中UTF-8可以占用1到4个字节,而UTF-16可以占用2或4个字节。UTF-32是一种固定宽度编码,它始终占用32位。汉
在Unicode中确切的2个字节或16位:01101100 01001001
。我可以看到这张表吗? - Jin Lim00100111 01100100
。实际上,这句话应该说:“U+2764是由两个字节组成的十六进制代码点。然而,为了表示这个代码点,UTF-8编码使用了3个字节。如何以及为什么UTF-8从00100111 01100100
到11100010 10011101 10100100
的过程将在下文中解释。” - BenderBoy
0
,110
,1110
,11110
或10
的字节)的地方。@brighty - SlySven