如何在 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 匹配?的主要内容,如果未能解决你的问题,请参考以下文章