我使用iconv库将使用UTF-8的现代输入源与使用Latin1(即CP1252(ISO-8859-1的超集))的旧系统进行接口(interface)。

该接口(interface)最近未能转换法语字符串“Éducation”,其中的“É”编码为hex 45 CC 81。请注意,目标编码确实有一个“É”字符,编码为C9

为什么iconv转换“É”失败?我检查了MacOS X 10.7.3附带的iconv命令行工具说它不能转换,并且PERL iconv模块也失败了。

令人困惑的是,“É”字符(编码为C3 89)的组合形式可以很好地转换。

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

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

最佳答案

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

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

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

我同意您的观点,iconv应该能够处理UTF8的NFC和NFD形式,但是直到有人修补了源代码之后,我们才必须手动检测此问题并进行处理,然后再将其传递给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 $_) );
}

关于unicode - 为什么iconv可以转换 "É"的分解形式而不是分解形式(从UTF-8到CP1252),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9892897/

10-14 19:09