根据维基百科UTF-8页面,我从人们那里听到了相互矛盾的观点。

它们是一样的,不是吗?有人能澄清一下吗?


当前回答

在阅读了大量关于这个话题的帖子和文章后,我的解释是:

1 - Unicode字符表

“Unicode”是一个巨大的表,它有21位宽,这21位提供了1,114,112个码点/值/字段/位置来存储字符。

在这1114112个码点中,有11111998个可以存储Unicode字符, 因为有2048个码点保留为代理,66个码点保留为非字符。 所以,有1,111,998个码位可以存储唯一的字符、符号、表情符号等。

然而,到目前为止,在这1114112个代码点中,只有144697个被使用。 这144,697个代码点包含了涵盖所有语言的字符,以及符号、表情符号等。

Each character in the "Unicode" is assigned to a specific codepoint aka has a specific value / Unicode number. For Example the character "❤", has the following value aka Unicode number "U+2764". The value "U+2764" takes exactly one codepoint out of the 1,114,112 codepoints. The value "U+2764" looks like that in binary: "11100010 10011101 10100100", which is exactly 3 bytes or 24bits (without the two empty space characters, each of which taking 1 bit, but I have added them for visual purposes only, in order to make the 24bits more readable, so please ignore them).

现在,我们的计算机应该如何知道这3个字节“11100010 10011101 10100100”是分开读还是一起读?如果将这3个字节分别读取,然后转换为字符,结果将是“Ô, Ø, ñ”,这与我们的心形表情符号“❤”有很大的不同。

2 -编码标准(UTF-8, ISO-8859, Windows-1251等)

为了解决这个问题,人们发明了编码标准。 自2008年以来,最流行的是UTF-8。UTF-8平均占所有网页的97.6%,这就是为什么我们将UTF-8,如下面的例子。

2.1 -什么是编码?

编码,简单来说就是将某物从一种东西转换成另一种东西。 在我们的例子中,我们正在将数据,更确切地说是字节转换为UTF-8格式, 我还想把这句话重新表述为:“将字节转换为UTF-8字节”,尽管它在技术上可能不正确。

2.2一些关于UTF-8格式的信息,以及为什么它如此重要

UTF-8使用最少1个字节来存储一个字符,最多4个字节。 多亏了UTF-8格式,我们可以拥有包含1个字节以上信息的字符。

这是非常重要的,因为如果不是UTF-8格式,我们就不可能有如此丰富的字母多样性,因为一些字母的字母不能装进1个字节,我们也不会有表情符号,因为每个表情符号至少需要3个字节。我很确定你现在已经明白了,让我们继续。

2.3汉字编码为UTF-8举例

现在,假设我们有汉字“汉”。

这个字符需要16个二进制位“01101100 01001001”,因此正如我们上面讨论的那样,我们不能读取这个字符,除非我们将它编码为UTF-8,因为计算机将无法知道这两个字节是分开读取还是一起读取。

将这个“汉”字符的2字节转换为我喜欢称其为UTF-8字节,将导致以下结果:

(正常的字节)"01101100 01001001" -> (UTF-8编码字节)"11100110 10110001 10001001"

现在,我们是如何得到3个字节而不是2个字节的呢?这怎么可能是UTF-8编码,把2个字节变成3个字节?

为了解释UTF-8编码是如何工作的,我将逐字复制@MatthiasBraun的回复,非常感谢他的精彩解释。

2.4 UTF-8编码是如何工作的?

这里有一个将字节编码为UTF-8的模板。这就是编码是如何发生的,如果你问我的话,我觉得非常令人兴奋!

现在,仔细看看下面的表格,然后我们将一起浏览它。

        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)

The "x" characters in the table above represent the number of "Free Bits", those bits are empty and we can write to them. The other bits are reserved for the UTF-8 format, they are used as headers / markers. Thanks to these headers, when the bytes are being read using the UTF-8 encoding, the computer knows, which bytes to read together and which seperately. The byte size of your character, after being encoded using the UTF-8 format, depends on how many bits you need to write. In our case the "汉" character is exactly 2 bytes or 16bits: "01101100 01001001" thus the size of our character after being encoded to UTF-8, will be 3 bytes or 24bits "11100110 10110001 10001001" because "3 UTF-8 bytes" have 16 Free Bits, which we can write to Solution, step by step below:

2.5解决方案:

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

2.6简介:

        A Chinese character:      汉
        its Unicode value:        U+6C49
        convert 6C49 to binary:   01101100 01001001
        encode 6C49 as UTF-8:     11100110 10110001 10001001

3 - UTF-8, UTF-16和UTF-32之间的区别

UTF-8、UTF-16和UTF-32编码之间差异的原始解释: https://javarevisited.blogspot.com/2015/02/difference-between-utf-8-utf-16-and-utf.html

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位。

其他回答

我已经检查了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 ?……”

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

Unicode为其存储库中的每个字符分配一个名称和一个数字(字符代码或代码点)。

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

,例如,

UCS字符= Unicode字符

UCS代码点= U+24B62

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

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

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

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

作为一个直截了当的简单回答:

Unicode是一种表示多种人类语言字符的标准。 UTF-8是一种编码Unicode字符的方法。


是的:我故意忽略了UTF-8的内部工作原理。