我听到了许多人的不同意见 - 根据维基百科 UTF-8页面。
它们不是一个东西吗?有人能澄清一下吗?
全世界有很多字符,例如 "$,&,h,a,t,?,张,1,=,+..."。
随之而来的是一家致力于这些字符的组织,他们制定了一个叫做“Unicode”的标准。
该标准如下:
PS:当然还有另一个组织叫做 ISO 维护另一个标准--“ISO 10646”,几乎相同。
如上所述,U+0024 只是一个位置,所以我们不能将“U+0024”保存在计算机中作为字符“$”。
必须有一种编码方法。
接着就有了编码方法,例如 UTF-8、UTF-16、UTF-32、UCS-2 等等。
在 UTF-8 下,代码点“U+0024”被编码成 00100100。
00100100 就是我们在计算机中保存为字符“$”所使用的值。
本文解释了所有细节: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是大(表),其中每个符号都映射到唯一的代码点。例如:あ
符号(字母)有一个(代码点):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.
如果我可以总结一下这个帖子中我所了解到的内容:
Unicode将字符分配给序数编号(用十进制表示)。(这些数字称为代码点。)
à -> 224
UTF-8是一种编码方式,它将这些序数(以十进制形式表示)翻译成二进制表示。
224 -> 11000011 10100000
请注意,我们谈论的是数字224的二进制表示,而不是它的二进制形式,即0b11100000。
我已经检查了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....
所以说我们有一个字符串:
Hello
在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?......
它们是同一件事情,不是吗?
不,它们不是。
我认为你引用的维基百科页面的第一句话已经很好地概括了:
UTF-8是一种可变长度字符编码,能够使用1到4个8位字节对Unicode中的所有1,112,064个有效代码点进行编码。
更详细地说:
Unicode is a standard, which defines a map from characters to numbers, the so-called code points, (like in the example below). For the full mapping, you can have a look here.
! -> U+0021 (21),
" -> U+0022 (22),
\# -> U+0023 (23)
UTF-8 is one of the ways to encode these code points in a form a computer can understand, aka bits. In other words, it's a way/algorithm to convert each of those code points to a sequence of bits or convert a sequence of bits to the equivalent code points. Note that there are a lot of alternative encodings for Unicode.
Joel在这里给出了非常好的解释和编程历史概述这里。
UTF-8 是一种使用 8 位序列编码 Unicode 字符的方法。
Unicode 是用于表示许多语言中的大量字符的标准。
01000001
、 11010011 10000101
或 11100101 10100011 10000110
或 11110001 10110001 10000010 10110001
。正如您所看到的,在UTF-8中,它可以是最小1个字节,最大4个字节。 - Jin Lim0
。当您想要使用2字节时,前3个数字是110
。当您想要使用3字节时,前4个数字是1110
。当您想要使用4字节时,前5个数字是11110
。嗯,你懂了吗? :) - Jin Lim简单明了地回答:
* 是的:我有意忽略了UTF-8的内部工作原理。
通常你从谷歌搜索到这里,想尝试不同的东西。
但是如何打印和转换所有这些字符集呢?
这里我列出了一些有用的单行命令。
在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")'
# 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
0
,110
,1110
,11110
或10
的字节)的地方。@brighty - SlySven