c-如何将完整的UTF-8十六进制值读入int



我要做的是让一个int接受一个UTF-8-16-32字符,这样它应该能够判断它是UTF-8、UTF-16还是UTF-32。

我使用fopen(fp, "rb")从文本文件中读取二进制值。我遇到了一个问题,一个字符被分成两个字节。

例如,如果我尝试读取字符CENT SIGN

文本文件input.txt包含:

¢

我得到:

utf code:       LATIN CAPITAL LETTER A WITH CIRCUMFLEX
binary:         11000010
hexadecimal:    0xC2
decimal:        194
character:      �
utf code:       CENT SIGN
binary:         10100010
hexadecimal:    0xA2
decimal:        162
character:      �
utf code:       LINE FEED (LF)
binary:         00001010
hexadecimal:    0xA
decimal:        10
character:

代码:

int ch;
while ((ch = fgetc(stream)) != EOF) {
printf(“utf code:t”);
findCode(ch); // HERE
write(1, “binary:         “, 16);
printBits(ch);
printf(“nhexadecimal:t%X”, ch);
printf(“ndecimal:t%d”, ch);
printf(“ncharacter:t%cnn”, ch);
}

注意:在UTF-8数据库中,CENT SIGN的二进制值为0xC2A211000010:10100010

问题是fgetc只读取1个字节。

您根本无法检测数据使用的是哪种UTF-what?编码,因为UTF-???UTF字符的编码

幸运的是,标记数据的编码可以在数据中使用,但这不是强制性的。BOM几乎是为了这个目的而发布的(请参阅注释),但您会发现许多UTF文档(无论采用何种编码)都没有遵循这种方法。在UTF-8、UTF-16或UTF-32编码中,相同的比特模式意味着不同的东西,因此您必须搜索编码错误来丢弃(可能是全部)无效编码,以猜测正确的编码。

如果文档的开头有一个BOM标记,那么该字节序列将允许您检测正在进行的编码,因为它的表示会根据实际编码获得不同的模式。

0xef, 0xbb, 0xbf  => UTF-8 (no endianness)
0xfe, 0xff        => UTF-16-BE (big endian)
0xff, 0xfe        => UTF-16-LE (little endian)
0x00, 0x00, 0xfe, 0xff => UTF-32-BE (big endian)
0xff, 0xfe, 0x00, 0x00 => UTF-32-LE (little endian)

但正如你所看到的,UTF-32-LEUTF-16-LE的开头相同,UTF-32-BEUTF-16-BE的开头一样,所以这并不能完全回答你的问题。例如,序列为0xff, 0xfe, 0x00, 0x00的文件是UTF-32-LE中没有数据(只有BOM)的完全有效文件,或者是UTF-16-LE中具有Unicode字符"NULL"U+0000字符的完全有效的文件。

最好的方法是将编码作为参数传递给输入例程,这样它们就可以对数据进行适当的解码。

编辑

在您使用的示例中,传递字符CENT SIGN(好吧,我假设您的意思是您有字符代码U+00A2,它以二进制形式表示(完成为UTF代码的21位表示)00000000010100010。如果你把这个字符编码为UTF-8,你会得到一个两个字符的编码,比如:0xe2, 0xa2,当你把它编码为UTF-16-LE时,你会获得:0xa2, 0x00,如果你把它编为UTF-16-BE,你会收到0x00, 0xa2,如果你编码为UTF-32-LE,你会接到0xa2, 0x00, 0x00, 0x00,如果你将它编码为UTF-32-BE,你会拿到0x00, 0x00, 0x00, 0xa2。这里的问题是,您使用4字节的序列来表示所有unicode,当编码UTF-32时(以及不同的顺序,取决于您是使用big-endian编码还是使用little-endian编码),当您使用UTF-16编码时(几乎所有的Unicode都低于限制U+10000,所以当它们不适合16位时,几乎所有的unicode都可以表示为单个UTF-16代码),当使用UTF-8编码时,可以表示为1到4字节的序列。因此,您必须知道的第一件事是,unicodeCODEPOINT与用于表示它的编码不同(这已经有了固定的编码),因此,通过对代码点(整个unicode表中字符的数字顺序)进行测试,您无法知道使用了哪种编码来编码unicode-char

备注

BOMNot a character U+fffe字符的替代用法。当它被放在文档的开头时,它会将其含义切换为表示deByte Order Mark character,因此这很不幸,因为它会迫使您将其包含两次,以防您想用它开始文档。顺便说一句,根据定义,这个字符不是字符,因此您很少将其视为普通文档字符。当UTF文档中发生某些解码时,它通常用作替换字符。

信用

BOM表示表来自维基百科页面

最新更新