我正在写一个需要从UTF-8的转码输入到ISO-8859-1的应用程序(拉丁文1)。
所有工作正常,但我有时会收到一些元音字符编码奇怪。 例如,拉丁1 C 2点(将0xEB)通常是为UTF-8 0xC3是0xAB,但有时也如0xC3 0×83为0xC2是0xAB。
这件事发生了一些来自不同来源的时间,并指出,第一和最后一个字符匹配我的期望,莫不是一种编码规则,我的图书馆不知道?
我正在写一个需要从UTF-8的转码输入到ISO-8859-1的应用程序(拉丁文1)。
所有工作正常,但我有时会收到一些元音字符编码奇怪。 例如,拉丁1 C 2点(将0xEB)通常是为UTF-8 0xC3是0xAB,但有时也如0xC3 0×83为0xC2是0xAB。
这件事发生了一些来自不同来源的时间,并指出,第一和最后一个字符匹配我的期望,莫不是一种编码规则,我的图书馆不知道?
$ "\xC3\x83\xC2\xAB"
ë
$ use Encode
$ decode 'UTF-8', "\xC3\x83\xC2\xAB"
ë
你已经双UTF-8编码。 编码::修复是处理的一个方法。
某些Unicode字符可以在一个组合和分解的形式来表示。 例如,德国元音-U ü
既可以由单个字符来表示ü
或通过u
接着¨
,其中文本渲染器后合并。
参见维基百科文章的Unicode等价的血淋淋的细节。
因此,统一的库通常提供的方法或功能正常化的字符串为这种或那种形式,所以你可以对它们进行比较。
(我回答您的问题的问题,“ 这是从门柱内侧问题显著不同。)
(“字符”通常是指串元素,它是在兽暧昧,这不是在这里使用正确的字。Unicode的期限为一个可视化表示,一字形,是“石墨烯”。)
是的,有超过的代码点序列可以产生相同的石墨烯。 例如,无论是
U+00EB LATIN SMALL LETTER E WITH DIAERESIS
和
U+0065 LATIN SMALL LETTER E
U+0308 COMBINING DIAERESIS
应显示为“E”。 让我们看看你的浏览器如何做:
在UTF-8,这些码点将被编码为
人们会使用Unicode的正常化::的NFC
或NFD
为字符串正常化的两种格式(你的选择)之一。
$ perl -MUnicode::Normalize -E'
$x = "\x{00EB}";
$y = "\x{0065}\x{0308}";
say $x eq $y ?1:0;
say NFC($x) eq NFC($y) ?1:0;
say NFD($x) eq NFD($y) ?1:0;
'
0
1
1
还有一些所谓的UTF-8“超长”的编码。 (具体而言UTF-8,不是一般的UNICODE)在UTF-8,Unicode码点使用以下四种位模式之一编码:
1 0xxxxxxx
2 110xxxxx 10xxxxxx
3 1110xxxx 10xxxxxx 10xxxxxx
4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
的“X” s为代码点进行编码。 我们必须用最短的,所以U + 00EB会
0000 0000 1110 1011
--- ---- ----
----- ------
110xxxxx 10xxxxxx
11000011 10101011
C3 AB
但是,聪明的人会做
0000 0000 1110 1011
---- ---- ---- ----
---- ------ ------
1110xxxx 10xxxxxx 10xxxxxx
11100000 10000011 10101011
E0 83 AB
应用程序应该拒绝E0 83 AB(或至少将其转换为C3 AB),但有些不这样做,可能会导致安全问题。 Perl的编码模块,把该序列为无效,所以它不应该是Perl的一个问题。