UTF-8与Unicode

我听到了人们的意见冲突 – 根据维基百科的说法, 请看这里 。

他们是一样的东西,不是吗? 有人可以澄清?

扩大其他人给出的答案:

我们有很多语言,电脑应该理想地显示很多字符。 Unicode为每个字符分配一个唯一的编号或代码点。

计算机处理像字节这样的数字……在这里忽略了一些历史logging,而忽略了内存寻址问题,8位计算机将8位字节视为硬件中最容易表示的最大数字单位,16位计算机将扩展那到两个字节,等等。

像ASCII这样的旧字符编码是从(预)8位时代开始的,并且试图将当时计算中的主要语言(即英语)塞进0到127(7位)的数字中。 在字母表中有26个字母,包括大写字母和非大写字母,数字和标点符号,这些字母都很好用。 对于其他非英语语言,ASCII扩展了第8位,但是根据所显示的语言,通过此扩展可获得的额外128个数字/代码点将映射到不同的字符。 ISO-8859标准是这种映射的最常见forms; ISO-8859-1和ISO-8859-15(也被称为ISO-Latin-1,latin1,是的,还有8859 ISO标准的两个不同版本)。

但是,如果要表示来自多种语言的字符,这还不够,因此将所有可用字符填充到单个字节中将不起作用。

基本上有两种不同types的编码:通过添加更多位来扩展数值范围。 这些编码的例子是UCS2(2字节= 16位)和UCS4(4字节= 32位)。 它们本质上与ASCII和ISO-8859标准有相同的问题,因为它们的数值范围仍然是有限的,即使极限高得多。

另一种types的编码使用每个字符可变数量的字节,最常见的编码是UTF编码。 所有UTF编码的工作方式大致相同:您select单位大小,对于UTF-8是8位,对于UTF-16是16位,对于UTF-32是32位。 标准然后将这些位中的一些定义为标志:如果它们被设置,则单元序列中的下一个单元被认为是同一个字符的一部分。 如果他们没有设置,这个单位完全代表一个字符。 因此,最常见的(英文)字符在UTF-8中只占用一个字节(UTF-16中的两个,UTF-32中的四个),但其他语言字符可占用六个字节或更多。

多字节编码(在上面的解释之后我应该说多单元)具有相对节省空间的优点,但是诸如查找子串,比较等的操作都必须将字符解码为Unicode码点之前可以执行这些操作(虽然有一些快捷方式)。

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

Windows将所谓的“Unicode”string处理为UTF-16string,而现在大多数UNIX都默认使用UTF-8。 像HTTP这样的通信协议通常在UTF-8上工作得最好,因为UTF-8的单元大小与ASCII相同,而且大多数这样的协议都是在ASCII时代devise的。 另一方面,在表示所有生活语言时,UTF-16提供了最好的平均空间/处理性能。

Unicode标准定义的代码点less于可以用32位表示的代码点。 因此,出于所有的实际目的,UTF-32和UCS4成为相同的编码,因为你不太可能需要处理UTF-32中的多单元字符。

希望能够填补一些细节。

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

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

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

一些关于Unicode的参考:

  • Unicode联盟网站 ,特别是教程部分
  • 乔尔的文章
  • 我自己的文章 (面向.NET的)

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

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

没有什么不可思议的,这很简单。 现在,假设我们决定将这个angular色存储在我们的硬盘上。 为此,我们需要以二进制格式存储字符。 我们可以简单地将它存储为“01101100 01001001”。 完成!

但是等一等,是'01101100 01001001'一个字还是两个字? 你知道这是一个angular色,因为我告诉过你,但是当一台电脑读取它时,它不知道。 所以我们需要某种“编码”来告诉计算机把它当作一个整体。

这是“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 

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

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

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

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

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

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

例如,

UCS字符= Unicode汉字

UCS代码点= U + 24B62

UTF-8编码= F0 A4 AD A2(hex)= 11110000 10100100 10101101 10100010(bin)

Unicode只是一个标准,它定义了一个字符集( UCS )和编码( UTF )来编码这个字符集。 但一般来说,Unicode是指字符集而不是标准。

阅读绝对最低限度每个软件开发人员肯定,积极必须知道Unicode和字符集(没有借口!)和Unicode在5分钟内 。

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

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

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

这是一个随机的例子sorting列表 。

我已经检查了Gumbo答案中的链接,我想将这些东西的一部分粘贴到Stack Overflow上。

“……有些人误解为Unicode只是一个16位的代码,每个字符需要16位,因此有65536个可能的字符,这实际上并不正确,这是关于Unicode的最常见的神话所以如果你觉得这样,不要不好意思。

实际上,Unicode对字符的思维方式是不一样的,你必须了解Unicode的思维方式,否则没有任何意义。

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

A – > 0100 0001

在Unicode中,一个字母映射到一个叫做代码点的东西,这个代码点仍然只是一个理论概念。 内存中或磁盘上的代码点是如何performance的……“

“…每个字母表中的每个柏拉图字母都由Unicode联合体分配一个幻数:U + 0639,这个幻数叫做代码点,U +是Unicode,数字是hex。 U + 0639是阿拉伯字母Ain,英文字母A是U + 0041 ….“

“…好吧,我们说有一个string:

你好

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

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

只是一堆代码点。 数字,真的。 我们还没有提到如何将这些信息存储在内存中,或者在电子邮件中表示出来……“

“…这是编码进来的地方。

Unicode编码的最早想法是导致两个字节的神话,嘿,让我们把这些数字分别存储在两个字节中。 所以你好

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

对? 不是那么快! 难道它不是:

48 00 65 00 6C 00 6C 00 6F 00? ……”

1. Unicode

世界上有很多人物,比如“$,&,h,a,t,?,张,1,=,+ …”。

然后有一个专门负责这些angular色的组织,

他们制定了一个叫做“Unicode”的标准。

标准如下:

  • 创build一个表格,其中每个位置被称为“代码点”或“代码位置”。
  • 整个职位从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是我们保存在“$”计算机中的值。

Unicode是一个范围广泛的标准,它定义了超过130,000个字符,并分配了一个数字代码(一个“代码点”)。 它还定义了如何对文本进行sorting,规范化,更改大小写的规则。 Unicode中的字符由0到0x10FFFF的代码点表示,尽pipe一些代码点是保留的,不能用于字符。

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

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

UTF-8的devise考虑到了这些特性:

  • ASCII字符的编码与ASCII中的字符完全相同,因此ASCIIstring也可以用作UTF-8。

  • 二进制sorting:使用朴素二进制sortingsortingUTF-8string仍将导致所有代码点按数字顺序sorting。

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

  • UTF-8可以很容易地validation,并由validation器区分其他字符编码。 其他8位或多字节编码的文本也很less会validation为UTF-8。

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