UTF-8和Unicode有什么区别

时间:2009-03-13 17:06:46

标签: unicode encoding utf-8 character-encoding terminology

根据Wikipedia UTF-8页面,我听到了人们的相互矛盾的意见。

他们是一回事,不是吗?有人可以澄清吗?

15 个答案:

答案 0 :(得分:434)

扩大其他人给出的答案:

我们有很多语言,其中包含许多计算机应该理想显示的字符。 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,4个UTF-32),但其他语言字符可占用六个字节或更多。

多字节编码(我应该说上面解释后的多单元)具有相对节省空间的优点,但是查找子字符串,比较等操作的缺点都是必须解码字符在执行此类操作之前进行unicode代码点(但有一些快捷方式)。

UCS标准和UTF标准都对Unicode中定义的代码点进行编码。从理论上讲,这些编码可用于编码任何数字(在编码支持的范围内) - 但当然这些编码用于编码Unicode代码点。那是你们之间的关系。

Windows将所谓的“Unicode”字符串作为UTF-16字符串处理,而大多数UNIX默认为UTF-8。 HTTP等通信协议往往最适合UTF-8,因为UTF-8中的单位大小与ASCII相同,大多数此类协议都是在ASCII时代设计的。另一方面,UTF-16在表示所有生活语言时提供最佳的平均空间/处理性能。

Unicode标准定义的代码点数少于32位代码。因此,出于所有实际目的,UTF-32和UCS4成为相同的编码,因为您不太可能必须处理UTF-32中的多单元字符。

希望填写一些细节。

答案 1 :(得分:189)

不幸的是,“Unicode”以各种不同的方式使用,具体取决于上下文。它最正确的用法(IMO)是一个编码字符集 - 即一组字符和字符与表示它们的整数代码点之间的映射。

UTF-8是一种字符编码 - 一种从字节序列转换为字符序列的方法,反之亦然。它涵盖了整个Unicode字符集。 ASCII被编码为每个字符一个字节,其他字符根据其确切的代码点占用更多字节(对于所有当前定义的代码点最多4个字节,即高达U-0010FFFF,实际上4个字节可以应对U型001FFFFF)。

当“Unicode”用作字符编码的名称(例如,作为.NET Encoding.Unicode属性)时,它通常表示UTF-16,它将最常见的字符编码为两个字节。某些平台(特别是.NET和Java)使用UTF-16作为其“本机”字符编码。如果您需要担心无法以单个UTF-16值编码的字符(它们被编码为“代理对”),这会导致毛病问题 - 但大多数开发人员从不担心这一点,IME。

关于Unicode的一些参考:

答案 2 :(得分:180)

让我用一个例子来说明这个话题:

A chinese character:      汉
it's unicode value:       U+6C49
convert 6C49 to binary:   01101100 01001001

到目前为止,没有什么神奇的东西,它非常简单。现在,让我们说我们决定将这个角色存储在我们的硬盘上。为此,我们需要以二进制格式存储字符。我们可以简单地将其存储为' 01101100 01001001'。完成!

但是等一下,是' 01101100 01001001'一个字符或两个字符?你知道这是一个角色,因为我告诉过你,但是当一台电脑看到它时,它根本不知道。所以我们需要某种"编码"告诉计算机将其视为一个。

这是UTF-8'的规则。进来了:http://www.fileformat.info/info/unicode/utf8.htm

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)

根据上表,如果我们想使用' UTF-8'来存储这个角色?格式,我们需要在角色前面添加一些标题'。我们的中文字符是16位长(自己计算二进制值),所以我们将使用第3行的格式,因为它提供了足够的空间:

Header  Place holder    Fill in our Binary   Result         
1110    xxxx            0110                 11100110
10      xxxxxx          110001               10110001
10      xxxxxx          001001               10001001

将结果写在一行:

11100110 10110001 10001001

这是中文字符的UTF-8(二进制)值! (自己确认一下:http://www.fileformat.info/info/unicode/char/6c49/index.htm

摘要

A chinese character:      汉
it's unicode value:       U+6C49
convert 6C49 to binary:   01101100 01001001
embed 6C49 as UTF-8:      11100110 10110001 10001001

答案 3 :(得分:107)

它们不是一回事 - UTF-8是一种编码Unicode的特殊方式。

根据您的应用程序和您打算使用的数据,您可以选择许多不同的编码。据我所知,最常见的是UTF-8,UTF-16和UTF-32。

答案 4 :(得分:59)

Unicode仅定义代码点,即表示字符的数字。如何将这些代码点存储在内存中取决于您使用的编码。 UTF-8是编码Unicode字符的一种方式,等等。

答案 5 :(得分:28)

Unicode 是一种标准,它与ISO / IEC 10646一起定义了通用字符集(UCS),它是几乎所有字符所需的所有现有字符的超集。已知语言。

Unicode为其指令表中的每个字符分配一个名称和一个数字(字符代码代码点)。

UTF-8编码,是一种在计算机内存中以数字方式表示这些字符的方法。 UTF-8将每个代码点映射为八位字节序列(8位字节)

例如,

UCS Character = Unicode Han Character

UCS代码点= U + 24B62

UTF-8编码= F0 A4 AD A2(十六进制)= 11110000 10100100 10101101 10100010(bin)

答案 6 :(得分:24)

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

答案 7 :(得分:21)

现有的答案已经解释了很多细节,但这里有一个非常简短的答案,最直接的解释和例子。

Unicode是将字符映射到代码点的标准
每个字符都有一个唯一的代码点(标识号),这是一个像9731的数字。

UTF-8是代码点的 编码
为了将所有字符存储在磁盘上(在文件中),UTF-8将字符分成最多4个八位字节(8位序列) - 字节。 UTF-8是几种编码之一(表示数据的方法)。例如,在Unicode中,(十进制)代码点9731表示一个雪人(),它由UTF-8中的3个字节组成:E2 98 83

这里是sorted list with some random examples

答案 8 :(得分:14)

1。 Unicode的

世界上有很多角色,比如" $,&,h,a,t,?,张,1,=,+ ......"。

然后有一个致力于这些角色的组织,

他们制定了一个名为" Unicode"。

的标准

标准如下:

  • 创建一个表单,其中每个位置都被调用"代码点"或"代码位置"。
  • 整个职位从U + 0000到U + 10FFFF;
  • 到目前为止,某些位置已填充字符,其他位置已保存或为空。
  • 例如,位置" U + 0024"充满了角色" $"。
PS:当然还有另一个名为ISO的组织维持着另一个标准 - " ISO 10646"几乎相同。

2。 UTF-8

如上所述,U + 0024只是一个位置,所以我们无法保存" U + 0024"在计算机中为角色" $"。

必须有编码方法。

然后有编码方法,如UTF-8,UTF-16,UTF-32,UCS-2 ....

在UTF-8下,代码点" U + 0024"编码为00100100。

00100100是我们在计算机中为" $"。

保存的值

答案 9 :(得分:12)

我已经检查过Gumbo答案中的链接,我想在这里粘贴这些东西的一部分也存在于Stack Overflow中。

“......有些人误以为Unicode只是一个16位代码,每个字符占16位,因此有65,536个可能的字符。这实际上并不正确。这是最常见的关于Unicode的神话,所以如果你这么想,不要心疼。

事实上,Unicode有一种不同的思考角色的方式,你必须要理解Unicode的思维方式或者什么都没有意义。

到目前为止,我们假设一个字母映射到一些可以存储在磁盘或内存中的位:

A - > 0100 0001

在Unicode中,字母映射到称为代码点的东西,这仍然只是一个理论概念。如何在内存或磁盘上表示代码点是另一个故事......“

“...每个字母表中的每个柏拉图字母都由Unicode联盟分配一个幻数,编号如下:U + 0639。这个神奇的数字称为代码点.U +表示”Unicode“和数字是十六进制的.U + 0639是阿拉伯字母Ain。英文字母A是U + 0041 ....“

“......好吧,所以说我们有一个字符串:

您好

,在Unicode中,对应于这五个代码点:

U + 0048 U + 0065 U + 006C U + 006C U + 006F。

只是一堆代码点。数字,真的。我们还没有说过如何将其存储在内存中或在电子邮件中表示它......“

“......这就是编码的来源。

Unicode编码最早的想法导致了关于这两个字节的神话,嘿,让我们将这些数字分别存储在两个字节中。所以 Hello 变为

00 48 00 65 00 6C 00 6C 00 6F

右?没那么快!不可能也是:

48 00 65 00 6C 00 6C 00 6F 00? ......“

答案 10 :(得分:3)

Unicode 是一个广泛的标准,它定义了超过130,000个字符,并为每个字符分配一个数字代码(“代码点”)。它还定义了如何对文本进行排序,规范化,更改案例等的规则。 Unicode中的字符由从0到0x10FFFF的代码点表示,但有些代码点是保留的,不能用于字符。

Unicode中的代码可以用多种编码表示。最简单的是UTF-32,它简单地将代码点编码为32位整数,每个整数为4个字节宽。

UTF-8 是另一种编码,并迅速成为事实上的标准。它编码为字节值序列。每个代码点可以使用可变数量的这些字节。 ASCII范围内的代码点是裸编码的,与ASCII兼容。超出此范围的代码点使用可变数量的字节,可以是2,3或4,具体取决于它们所处的范围。

UTF-8的设计考虑了这些属性:

  • ASCII字符的编码方式与ASCII格式完全相同,因此ASCII字符串也可用作UTF-8。

  • 二进制排序:使用朴素二进制排序对UTF-8字符串进行排序仍会导致所有代码点按数字顺序排序。

  • ASCII范围之外的字符不使用ASCII范围内的任何字节,确保它们不会被误认为是ASCII字符。这也是一项安全功能。

  • UTF-8可以轻松验证,并通过验证器与其他字符编码区分开来。其他8位或多字节编码中的文本很少也会验证为UTF-8。

  • 随机访问:在UTF-8字符串中的任何一点,都可以判断该位置的字节是否是字符的第一个字节,并且可以回溯到该字符的开头,而不是需要在字符串的开头引用任何东西。

答案 11 :(得分:0)

  

他们是一回事,他们不是吗?

不,他们不是。

我认为您引用的Wikipedia page的第一句话给出了一个很好的简短摘要:

  

UTF-8是一种可变宽度字符编码,能够使用一到四个8位字节对Unicode中的所有1,112,064个有效代码点进行编码。

详细说明:

  • Unicode 是一个标准,它定义了地图从字符到数字,即所谓的代码点,(如在下面的例子中)。对于完整映射,您可以查看here

    ! -> U+0021 (21),  
    " -> U+0022 (22),  
    \# -> U+0023 (23)
    
  • UTF-8是以计算机可以理解的形式编码这些代码点的方法之一,又名。换句话说,它是将每个代码点转换为比特序列或将比特序列转换为等效代码点的方法/算法。请注意,Unicode有很多替代编码。

乔尔给出了一个非常好的解释和历史概述here

答案 12 :(得分:0)

UTF-8 是一种使用8位序列编码Unicode字符的方法。

Unicode 是用于表示来自多种语言的各种字符的标准。

答案 13 :(得分:0)

如果我可以总结一下我从该线程收集的信息:

Unicode将个字符转换为序数(十进制形式)

à = 224

UTF-8是一种将这些数字“翻译”为二进制表示形式 的编码。

224 = 11000011 10100000

答案 14 :(得分:0)

本文介绍了所有详细信息 http://kunststube.net/encoding/

写缓冲区

如果您使用UTF8编码写入4字节缓冲区(符号),则二进制文件将如下所示:

00000000 11100011 10000001 10000010

如果您使用UTF16编码写入4字节缓冲区符号,则二进制文件将如下所示:

00000000 00000000 00110000 01000010

如您所见,根据您在内容中使用的语言,这将相应地影响您的记忆力。

例如对于此特定符号: UTF16编码效率更高,因为我们有2个备用字节可用于下一个符号。但这并不意味着您必须对日本字母使用UTF16。

从缓冲区读取

现在,如果您想读取上述字节,则必须知道其写入的编码并正确解码回去。

例如如果您解码此:   00000000 11100011 10000001 10000010 转换为UTF16编码,您将得到而不是

注意:编码和Unicode是两件事。 Unicode是很大的(table),每个符号都映射到一个唯一的代码点。例如符号(字母)带有(code point) 30 42 (十六进制)。另一方面,编码是一种在存储到硬件时将符号转换为更合适方式的算法。

30 42 (hex) - > UTF8 encoding - > E3 81 82 (hex), which is above result in binary.

30 42 (hex) - > UTF16 encoding - > 30 42 (hex), which is above result in binary.

enter image description here