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

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


当前回答

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

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

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

这是一个排序的列表,其中有一些随机的例子。

其他回答

你通常从谷歌开始,然后想尝试不同的东西。 但是如何打印和转换所有这些字符集呢?

这里我列出了一些有用的一行程序。

Powershell:

# Print character with the Unicode point (U+<hexcode>) using this: 
[char]0x2550

# With Python installed, you can print the unicode character from U+xxxx with:
python -c 'print(u"\u2585")'

如果你有更多的Powershell trix或快捷方式,请评论。

在Bash中,你会喜欢libiconv和util-linux包中的iconv、hexdump和xxd(可能在其他*nix发行版中命名不同)。

# To print the 3-byte hex code for a Unicode character:
printf "\\\x%s" $(printf '═'|xxd -p -c1 -u)
#\xE2\x95\x90

# To print the Unicode character represented by hex string:
printf '\xE2\x96\x85'
#▅

# To convert from UTF-16LE to Unicode
echo -en "════"| iconv -f UTF-16LE -t UNICODEFFFE

# To convert a string into hex: 
echo -en '═�'| xxd -g 1
#00000000: e2 95 90 ef bf bd

# To convert a string into binary:
echo -en '═�\n'| xxd -b
#00000000: 11100010 10010101 10010000 11101111 10111111 10111101  ......
#00000006: 00001010

# To convert a binary string into hex:
printf  '%x\n' "$((2#111000111000000110000010))"
#e38182

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

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

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

这是一个排序的列表,其中有一些随机的例子。

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)

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

这篇文章解释了所有细节 http://kunststube.net/encoding/

写入缓冲区

如果你写入一个4字节的缓冲区,符号あUTF8编码,你的二进制将看起来像这样:

00000000 11100011 10000001 10000010

如果你写入一个4字节的缓冲区,使用UTF16编码的符号あ,你的二进制将看起来像这样:

00000000 00000000 00110000 01000010

正如你所看到的,根据你在内容中使用的语言,这将相应地影响你的记忆。

例如,对于这个特定的符号:あUTF16编码更有效,因为我们有2个空闲字节用于下一个符号。但这并不意味着你必须使用UTF16来表示日本字母。

从缓冲区读取

现在,如果你想读取上面的字节,你必须知道它是用什么编码写的,并正确解码回来。

例:如果你解码这个: 00000000 11100011 10000001 10000010 转换为UTF16编码,你将得到臣而不是あ

注意:Encoding和Unicode是两个不同的东西。Unicode是一个大(表),每个符号都映射到一个唯一的码点。例如,あ符号(字母)有一个(码位):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.