Unicode 为什么iconv可以转换“的预合成形式而不是分解形式?”É&引用;(从UTF-8到CP1252)

Unicode 为什么iconv可以转换“的预合成形式而不是分解形式?”É&引用;(从UTF-8到CP1252),unicode,iconv,Unicode,Iconv,我使用iconv库从使用UTF-8的现代输入源连接到使用Latin1(又名CP1252)(ISO-8859-1超集)的传统系统 接口最近未能转换法语字符串“Éeducation”,其中“É”编码为十六进制45 CC 81。注意,目标编码确实有一个“É”字符,编码为C9 为什么iconv无法转换“É”?我检查了MacOS X 10.7.3提供的iconv命令行工具是否表示无法转换,以及PERL iconv模块是否也出现故障 更令人费解的是,“É”字符的预合成形式(编码为c389)转换得很好 这是i

我使用iconv库从使用UTF-8的现代输入源连接到使用Latin1(又名CP1252)(ISO-8859-1超集)的传统系统

接口最近未能转换法语字符串“Éeducation”,其中“É”编码为十六进制
45 CC 81
。注意,目标编码确实有一个“É”字符,编码为
C9

为什么iconv无法转换“É”?我检查了MacOS X 10.7.3提供的iconv命令行工具是否表示无法转换,以及PERL iconv模块是否也出现故障

更令人费解的是,“É”字符的预合成形式(编码为
c389
)转换得很好

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

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

在调用iconv之前使用a(在本例中,使用规范化形式C)


处理字符编码(字符的不同表示,或者更准确地说,代码点,作为字节序列)并在它们之间进行转换的程序应该将预合成和合成形式视为不同的。分解的赤道是两个代码点,因此不同于预合成赤道,预合成赤道是一个代码点。

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

处理Mac文件名时,可以将iconv与“utf8 Mac”字符集选项一起使用。它还考虑了一些因素

但是,非mac版本的iconv或libiconv不支持这一点,我也找不到mac上提供这一支持的源代码

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

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

#/usr/bin/perl
使用Encode qw/decode_utf8 Encode_utf8/;
使用Unicode::规范化;
而(){
打印编码utf8(NFC(解码utf8$);
}

谢谢。这并不能回答为什么iconv会将预合成的字符映射到目标编码,而不是(公认的不同)分解的字符。为什么不能两者兼而有之?为什么不是后者而不是前者呢?对于转换工具/库,如果不是错误,那就是失败。事实上,你是不正确的。没有理由不将分解的字符映射到其CP-1252等效字符。无论“É”使用的是一种表示法还是另一种表示法,它都可以而且应该映射到CP-1252“É”字符。“U+0045 U+0301是两个编码字符”:我质疑这一说法。你有证据吗?我看不出有什么理由不把这当作一个角色。如果要用Unicode表示两个“E”和“')字符,可以使用U+0045U+00B4,而不是U+0045U+0301。这正是组合变音符号的要点:从两个(或更多)字符中构造一个字符。我做到了。Unicode将字符定义为“存储文本的最小可解释单元”。如果没有所应用的文本元素(前一个基本字符),则不能解释组合急性重音。因此,组合式尖锐重音不是字符。在我的上下文中,序列U+0045u+0301实际上是存储文本的最小可解释单元。因此,它只有一个字符。好吧,我放弃它。但你没有提供任何令人信服的证据证明你是对的。你给出的报价不是。倒数会多一点。另一方面,我提供的引语似乎更倾向于我的解释,顺便说一句,这似乎是常识:“É”与“É”相同。当然,常识往往是不正确的。谢谢你的意见,我认为这是不正确的。