为什么iconv可以转换预组合形式而不是“É”的分解形式(从UTF-8到CP1252)

时间:2012-03-27 15:41:02

标签: unicode iconv

我使用iconv库从使用UTF-8的现代输入源连接到使用Latin1的遗留系统,即CP1252(ISO-8859-1的超集)。

界面最近无法转换法语字符串“Éducation”,其中“É”被编码为十六进制45 CC 81。请注意,目标编码的确具有“É”字符,编码为C9

为什么iconv无法转换为“É”?我检查过MacOS X 10.7.3提供的iconv命令行工具说它无法转换,PERL iconv模块也失败了。

令人费解的是,“É”字符的预组合形式(编码为C3 89)转换得很好。

这是iconv的错误还是我错过了什么?

请注意,如果我尝试转换为UTF-16(其中“É”编码为00 C9编组或00 45 03 01已分解),我也会遇到同样的问题。

2 个答案:

答案 0 :(得分:5)

不幸的是,除了Mac OS X上安装的版本之外,iconv确实没有处理UTF-8中的分解字符。

处理Mac文件名时,您可以使用iconv与" utf8-mac "字符集选项。它还考虑了一些idiosyncrasies of the Mac decomposed form

但是,iconv或libiconv的非mac版本不支持此功能,而且我找不到Mac上使用的提供此支持的源代码。

我同意你的看法,iconv应该能够处理NFC和NFD形式的UTF8,但是在有人补充源代码之前我们必须手动检测它并在将内容传递给iconv之前处理它。

面对这个恼人的问题,我使用了Jukka建议的Perl的Unicode :: Normalize模块。

#!/usr/bin/perl

use Encode qw/decode_utf8 encode_utf8/;
use Unicode::Normalize;

while (<>) {
    print encode_utf8( NFC(decode_utf8 $_) );
}

答案 1 :(得分:0)

在调用iconv之前使用normalizer(在本例中为规范化表格C)。

处理字符编码(字符的不同表示,或者更准确地说,代码点,字节序列)以及在它们之间进行转换的程序应该预期将预合成和合成的表单视为不同的。分解后的É是两个代码点,因此与预先组合的É不同,后者是一个代码点。