我有角色“ö”。如果我查看this UTF-8 table,我会看到它具有十六进制值F6
。如果我查看Unicode table,我会看到“ö”的索引为E0
和16
。如果我添加两者,我会得到代码点F6
的十六进制值。这是二进制值1111 0110
。
1)如何从十六进制值F6
获取索引E0
和16
?
2)我不知道如何从F6
到两个字节C3
B6
......
因为我没有得到结果我试图走另一条路。 “ö”在ISO-8859-1中表示为“Ô。在UTF-8 table我可以看到“Ô具有十进制值195
而“¶”具有十进制值182
。转换为位为1100 0011 1011 0110
。
过程:
查看table并获取字符“ö”的unicode。根据索引E0
和16
计算得到Unicode U+00F6
。
根据wildplasser发布的算法,您可以计算编码的UTF-8值C3
和B6
。
在二进制表单中,您获得1100 0011 1011 0110
,其对应于小数值195
和182
。
如果这些值被解释为ISO 8859-1(只有1个字节),那么你会得到“¶”。
PS:我还找到了this link,它显示了第2步的值。
答案 0 :(得分:7)
您使用的网页让您感到困惑。您的“UTF-8表”或“Unicode表”都没有为您提供UTF-8中代码点的值。它们都只是列出了字符的Unicode值。
在Unicode中,每个字符(“代码点”)都有一个唯一的编号。角色ö
被分配了代码点U+00F6
,其中十六进制为F6
,十进制为246
。
UTF-8是Unicode的representation,使用每个Unicode代码点一到四个字节的序列。在那篇文章中描述了从32位Unicode代码点到UTF-8字节序列的转换 - 一旦你习惯它,这很简单。当然,计算机一直都是这样做的,但是你可以用铅笔和纸轻松地完成它,并且可以通过一些练习来实现。
如果进行转换,您会看到U+00F6
转换为UTF-8序列C3 B6
或二进制1100 0011 1011 0110
,这就是UTF-8表示的原因ö
。
问题的另一半是关于ISO-8859-1。这是一种通常称为“Latin-1”的字符编码。 Latin-1编码的数值与Unicode中的前256个代码点相同,因此{1}}在Latin-1中为ö
。
在UTF-8和标准Unicode代码点(UTF-32)之间进行转换后,获得Latin-1编码应该是微不足道的。但是,并非所有UTF-8序列/ Unicode字符都具有相应的Latin-1字符。
请参阅优秀文章The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!),以便更好地理解角色编码和它们之间的转换。
答案 1 :(得分:2)
unsigned cha_latin2utf8(unsigned char *dst, unsigned cha)
{
if (cha < 0x80) { *dst = cha; return 1; }
/* all 11 bit codepoints (0x0 -- 0x7ff)
** fit within a 2byte utf8 char
** firstbyte = 110 +xxxxx := 0xc0 + (char>>6) MSB
** second = 10 +xxxxxx := 0x80 + (char& 63) LSB
*/
*dst++ = 0xc0 | (cha >>6) & 0x1f; /* 2+1+5 bits */
*dst++ = 0x80 | (cha) & 0x3f; /* 1+1+6 bits */
return 2; /* number of bytes produced */
}
测试它:
#include <stdio.h>
int main (void)
{
char buff[12];
cha_latin2utf8 ( buff, 0xf6);
fprintf(stdout, "%02x %02x\n"
, (unsigned) buff[0] & 0xff
, (unsigned) buff[1] & 0xff );
return 0;
}
结果:
c3 b6