如何在java中将“i”与土耳其语i匹配?

时间:2015-06-09 06:45:41

标签: java unicode normalization unicode-normalization

我希望将英语(i)的“I”的小写字母与土耳其语(i)的“İ”的小写字母相匹配。它们是相同的字形,但它们不匹配。当我执行System.out.println("İ".toLowerCase());字符i和点打印时(此网站无法正确显示)

有没有办法匹配那些?(最好没有硬编码)我想让程序匹配与语言和utf代码无关的相同字形。这可能吗?

我测试了规范化没有成功。

public static void main(String... a) {
    String iTurkish = "\u0130";//"İ";
    String iEnglish = "I";
    prin(iTurkish);
    prin(iEnglish);
}

private static void prin(String s) {
    System.out.print(s);
    System.out.print(" -  Normalized : " + Normalizer.normalize(s, Normalizer.Form.NFD));
    System.out.print(" - lower case: " + s.toLowerCase());
    System.out.print(" -  Lower case Normalized : " + Normalizer.normalize(s.toLowerCase(), Normalizer.Form.NFD));
    System.out.println();

}

结果未在网站中正确显示,但第一行(iTurkish)的̇仍然接近小写i。

目的和问题

这将是一个多语言词典。我希望程序能够识别“İFEL”以“if”开头。为了确保它们不区分大小写,我首先将两个文本转换为小写。 İFEL成为i(点)fel并且“if”未被识别为其中的一部分

2 个答案:

答案 0 :(得分:10)

如果您打印出您所看到的字符的十六进制值,则差异很明显:

İ 0x130 - Normalized : İ 0x49 0x307 - Lower case: i̇ 0x69 0x307 - Lower case Normalized : i̇ 0x69 0x307
I 0x49 - Normalized : I 0x49 - Lower case: i 0x69 - Lower case Normalized : i 0x69

规范化土耳其语İ并不会为您提供英语I,而是会为您提供英语I,后跟变音符号0x307。这是正确的,并且可以通过规范化过程来预期。规范化不是"转换为ASCII"操作。正如Normalizer提到的文档一样,它所遵循的流程是一个非常严格定义的标准Unicode Standard Annex #15 — Unicode Normalization Forms

在标准化之前或之后有numerous ways to strip diacritics。您需要的将取决于您的用例的具体情况,但对于您的用例,我建议使用GuavaCharMatcher类在规范化后删除非ASCII字符,例如:< / p>

String asciiString = CharMatcher.ascii().retainFrom(normalizedString);

This answer更深入地了解了\p{InCombiningDiacriticalMarks}的作用,以及为什么它不理想。我的CharMatcher解决方案也不理想(链接的答案提供了更强大的解决方案),但为了快速解决问题,您可能会发现仅保留ASCII字符&#34;足够好&#34;。这更接近&#34;正确&#34;并且比基于Pattern的方法更快。

答案 1 :(得分:-1)

您可以使用以下代码:

public static void main(String... a) {

      String iTurkish = "\u0130";//"İ";
      String iEnglish = "I";
      prin(iTurkish);
      prin(iEnglish);


}

private static void prin(String s) {
    System.out.print(s);
    String nfdNormalizedString = Normalizer.normalize(s, Normalizer.Form.NFD);
    Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
    System.out.print(" -  Normalized : " + pattern.matcher(nfdNormalizedString).replaceAll(""));
    System.out.print(" - lower case: " + s.toLowerCase());
    System.out.print(" -  Lower case Normalized : " + Normalizer.normalize(pattern.matcher(nfdNormalizedString).replaceAll("").toLowerCase(), Normalizer.Form.NFD));
    System.out.println();

}

或者查看Converting Symbols, Accent Letters to English Alphabet