Java 将符号、重音字母转换为英文字母

Java 将符号、重音字母转换为英文字母,java,unicode,special-characters,diacritics,Java,Unicode,Special Characters,Diacritics,问题是,如你所知,有数千个字符,我想把所有相似的字符转换成英文字母表中的字母 例如,以下是一些转换: ҥ->H Ѷ->V Ȳ->Y Ǭ->O Ƈ->C tђє Ŧค๓เℓy --> the Family ... 我看到字母A/A有20多个版本。我不知道如何对它们进行分类。它们看起来像大海捞针 unicode字符的完整列表位于或。试着向下滚动,看看字母的变化 如何使用Java转换所有这些内容?请帮助我:(将任意Unicode“转换”为ASCII的问题在于字符的

问题是,如你所知,有数千个字符,我想把所有相似的字符转换成英文字母表中的字母

例如,以下是一些转换:

ҥ->H
Ѷ->V
Ȳ->Y
Ǭ->O
Ƈ->C
tђє Ŧค๓เℓy --> the Family
...
我看到字母A/A有20多个版本。我不知道如何对它们进行分类。它们看起来像大海捞针

unicode字符的完整列表位于或。试着向下滚动,看看字母的变化

如何使用Java转换所有这些内容?请帮助我:(

将任意Unicode“转换”为ASCII的问题在于字符的含义取决于区域性。例如,德语人士的“ß”应转换为“ss”,而英语人士可能会将其转换为“B”

此外,Unicode对于相同的标志符号有多个代码点

结果是,实现这一点的唯一方法是创建一个包含每个Unicode字符和要将其转换为的ASCII字符的大型表。您可以通过将带有重音符号的字符规范化为规范化形式KD来实现快捷方式,但并非所有字符都规范化为ASCII。此外,Unicode不定义符号的哪些部分是“口音”

下面是一个应用程序的一个小摘录:

switch (c)
{
    case 'A':
    case '\u00C0':  //  À LATIN CAPITAL LETTER A WITH GRAVE
    case '\u00C1':  //  Á LATIN CAPITAL LETTER A WITH ACUTE
    case '\u00C2':  //  Â LATIN CAPITAL LETTER A WITH CIRCUMFLEX
    // and so on for about 20 lines...
        return "A";
        break;

    case '\u00C6'://  Æ LATIN CAPITAL LIGATURE AE
        return "AE";
        break;

    // And so on for pages...
}

您可以尝试使用
unidecode
,它作为和提供。本质上,它作为一个巨大的查找表工作,其中每个unicode代码点都与ascii字符或字符串相关。

尝试“全部转换”是解决问题的错误方法

首先,你需要理解你正在尝试做的事情的局限性。正如其他人所指出的,变音符号的存在是有原因的:它们本质上是该语言字母表中唯一的字母,具有自己的含义/声音等:删除这些标记就如同替换英语单词中的随机字母一样。这是bef你甚至会考虑西里尔语言和其他基于脚本的文本,比如阿拉伯语,它根本不能“转换”成英语。

如果你必须以任何理由转换字符,那么唯一明智的方法是,首先要减少手头的任务范围。考虑输入的来源——如果你正在为“西方世界”编写一个应用程序(使用任何一个好短语),您不太可能需要解析阿拉伯语字符。类似地,Unicode字符集包含数百个数学和图形符号:用户无法(轻松)直接输入这些符号,因此您可以假设可以忽略它们

通过采取这些逻辑步骤,您可以将可能要解析的字符数减少到基于字典的查找/替换操作可行的程度。然后,创建字典就变成了一项小而乏味的工作,而执行替换则是一项琐碎的任务。如果您的语言支持本机Unicode字符rs(正如Java所做的那样)并正确地优化静态结构,这样的查找和替换往往非常快

这来自于开发一个应用程序的经验,该应用程序需要允许最终用户搜索包含变音字符的书目数据。查找数组(在我们的例子中)可能需要1个人日才能生成,以覆盖所有西欧语言的所有变音符号。

如果需要转换”òışöç->oeisoc”,您可以将此作为起点:

public class AsciiUtils {
    private static final String PLAIN_ASCII =
      "AaEeIiOoUu"    // grave
    + "AaEeIiOoUuYy"  // acute
    + "AaEeIiOoUuYy"  // circumflex
    + "AaOoNn"        // tilde
    + "AaEeIiOoUuYy"  // umlaut
    + "Aa"            // ring
    + "Cc"            // cedilla
    + "OoUu"          // double acute
    ;

    private static final String UNICODE =
     "\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9"             
    + "\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD" 
    + "\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177" 
    + "\u00C3\u00E3\u00D5\u00F5\u00D1\u00F1"
    + "\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF" 
    + "\u00C5\u00E5"                                                             
    + "\u00C7\u00E7" 
    + "\u0150\u0151\u0170\u0171" 
    ;

    // private constructor, can't be instanciated!
    private AsciiUtils() { }

    // remove accentued from a string and replace with ascii equivalent
    public static String convertNonAscii(String s) {
       if (s == null) return null;
       StringBuilder sb = new StringBuilder();
       int n = s.length();
       for (int i = 0; i < n; i++) {
          char c = s.charAt(i);
          int pos = UNICODE.indexOf(c);
          if (pos > -1){
              sb.append(PLAIN_ASCII.charAt(pos));
          }
          else {
              sb.append(c);
          }
       }
       return sb.toString();
    }

    public static void main(String args[]) {
       String s = 
         "The result : È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô,ç";
       System.out.println(AsciiUtils.convertNonAscii(s));
       // output : 
       // The result : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o,c
    }
}
公共类asciuitils{
私有静态最终字符串纯ASCII=
“aaeeiiouu”//grave
+“aaeeiiouuyy”//acute
+“aaeeiiouuyy”//扬抑
+“AaOoNn”//tilde
+“aaeeioouuyy”//umlaut
+“Aa”//环
+“抄送”//cedilla
+“OoUu”//双急性
;
私有静态最终字符串UNICODE=
“\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9”
+“\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD”
+“\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177”
+“\u00C3\u00E3\u00D5\u00F5\u00D1\u00F1”
+“\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF”
+“\u00C5\u00E5”
+“\u00C7\u00E7”
+“\u0150\u0151\u0170\u0171”
;
//私有构造函数,不能实例化!
专用AsciiUtils(){}
//从字符串中删除重音符号并替换为等效的ascii
公共静态字符串转换(字符串s){
如果(s==null)返回null;
StringBuilder sb=新的StringBuilder();
int n=s.长度();
对于(int i=0;i-1){
sb.append(纯ASCII字符(pos));
}
否则{
sb.附加(c);
}
}
使某人返回字符串();
}
公共静态void main(字符串参数[]){
字符串s=
“结果:È,É,Ê,Ë,Û,Ù,Î,À,Ô,ù,î,î,ç”;
System.out.println(AsciiUtils.convertnascii(s));
//输出:
//结果:E,E,E,E,U,U,I,I,A,A,O,E,E,E,E,U,U,I,I,A,A,O,c
}
}
JDK1.6提供了可用于此任务的java.text.Normalizer类


看一个例子

没有简单或通用的方法来做你想做的事情,因为你的主观意见是这些字母看起来像你想转换成的拉丁字母。它们实际上是单独的字母,有自己独特的名称和发音,只是表面上看起来像拉丁字母

如果你想要转换,你必须根据你认为非拉丁字母应该转换成的拉丁字母创建你自己的翻译表

import java.text.Normalizer;
import java.util.regex.Pattern;

public String deAccent(String str) {
    String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD); 
    Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
    return pattern.matcher(nfdNormalizedString).replaceAll("");
}
org.apache.commons.lang3.StringUtils.stripAccents("Añ");
    import com.ibm.icu.text.Transliterator; //ICU4J library import

    public static String TRANSLITERATE_ID = "NFD; Any-Latin; NFC";
    public static String NORMALIZE_ID = "NFD; [:Nonspacing Mark:] Remove; NFC";

    /**
    * Returns the transliterated string to convert any charset to latin.
    */
    public static String transliterate(String input) {
        Transliterator transliterator = Transliterator.getInstance(TRANSLITERATE_ID + "; " + NORMALIZE_ID);
        String result = transliterator.transliterate(input);
        return result;
    }
String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD)
    .replaceAll("[^\\p{ASCII}]", "");
org.apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter