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

Posted

技术标签:

【中文标题】如何在 java 中将“i”与土耳其语 i 匹配?【英文标题】:How do I match "i" with Turkish i in java? 【发布时间】:2015-08-23 20:13:26 【问题描述】:

我想将英语 (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(dot)fel 并且“if”不被识别为它的一部分

【问题讨论】:

这两个字母不是同一个 uni 码,所以它们不匹配。 你可以用commons-lang从字符串中去掉变音符号:org.apache.commons.lang3.StringUtils.stripAccents(String) @agad 不会阻止区分 i 和 ı 吗?如果没有办法,我会考虑。 @Zelldon true 但它们是相同的字形。归一化的点不匹配它们吗? commons.apache.org/proper/commons-lang/download_lang.cgi 【参考方案1】:

如果你打印出你看到的字符的十六进制值,区别就很明显了:

İ 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。您需要什么取决于您的用例的具体情况,但对于您的用例,我建议使用Guava 的CharMatcher 类在规范化后去除非ASCII 字符,例如:

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

This answer 更深入地介绍了\pInCombiningDiacriticalMarks 的作用,以及为什么它不理想。我的CharMatcher 解决方案也不理想(链接的答案提供了更强大的解决方案),但为了快速修复,您可能会发现只保留“足够好”的 ASCII 字符。这比基于Pattern 的方法更接近“正确”并且更快。

【讨论】:

+1,有趣的副作用"İ".toLowerCase() 似乎决定它需要分解角色。至少在这里... 似乎每个人都建议去掉变音符号。我可能会这样做。我想将“ıf”与“İF”匹配比不将“if”与“İF”匹配要好。很难,我不确定是否会是这种情况。 @WVrock - 正如您所介绍的那样,解决问题的最佳方法是去掉变音符号。您可能还有其他未告诉我们的要求,哪些可能需要不同的解决方案。但从广义上讲,如果您希望某人能够键入英文字符并将它们映射到土耳其语字符,您将不得不剥离 一些 信息,并且您将很难避免两者假阳性和假阴性。您的解决方案应尽量减少对您的用例不利的情况。 尽管这是引导我走向正确方向的答案,但我更喜欢 Rafiq 链接中的代码【参考方案2】:

您可以使用下面的代码:

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("\\pInCombiningDiacriticalMarks+");
    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

【讨论】:

从 Utils 类中复制代码并在此处显示为自己的代码并不是很好。 为什么不投票?我提供了链接“***.com/questions/1008802/converting-symbols-accent- letters-to-english-alphabet”。没看到吗? “阿加德” +1 用于提供指向答案的链接并使其适应给定的代码。即使您先提供链接然后澄清您正在使用其他人的代码会更好。

以上是关于如何在 java 中将“i”与土耳其语 i 匹配?的主要内容,如果未能解决你的问题,请参考以下文章

土耳其语 SQL 排序规则的问题(土耳其语“I”)

CSS:文本转换不适用于土耳其语字符

javascript İnput土耳其上层写作

Android facebook-sdk 在土耳其语中崩溃

在Java中将字符转换为整数

SQLite中的土耳其字符在使用LIKE表达式时