手动将字符从UTF-8转换为ISO-8859-1

时间:2011-10-26 13:57:36

标签: utf-8 iso-8859-1 latin1

我有角色“ö”。如果我查看this UTF-8 table,我会看到它具有十六进制值F6。如果我查看Unicode table,我会看到“ö”的索引为E016。如果我添加两者,我会得到代码点F6的十六进制值。这是二进制值1111 0110

1)如何从十六进制值F6获取索引E016
2)我不知道如何从F6到两个字节C3 B6 ......

因为我没有得到结果我试图走另一条路。 “ö”在ISO-8859-1中表示为“Ô。在UTF-8 table我可以看到“Ô具有十进制值195而“¶”具有十进制值182。转换为位为1100 0011 1011 0110

过程:

  1. 查看table并获取字符“ö”的unicode。根据索引E016计算得到Unicode U+00F6

  2. 根据wildplasser发布的算法,您可以计算编码的UTF-8值C3B6

  3. 在二进制表单中,您获得1100 0011 1011 0110,其对应于小数值195182

  4. 如果这些值被解释为ISO 8859-1(只有1个字节),那么你会得到“¶”。

  5. PS:我还找到了this link,它显示了第2步的值。

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