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

时间:2009-06-17 18:31:24

标签: java unicode special-characters diacritics

问题在于,如您所知,有数千个字符in the Unicode chart,我想将所有相似字符转换为英文字母中的字母。

例如,这里有一些转换:

ҥ->H
Ѷ->V
Ȳ->Y
Ǭ->O
Ƈ->C
tђє Ŧค๓เℓy --> the Family
...

我看到有超过20个版本的字母A / a。而且我不知道如何对它们进行分类。它们看起来像大海捞针。

unicode字符的完整列表位于http://www.ssec.wisc.edu/~tomw/java/unicode.htmlhttp://unicode.org/charts/charindex.html。只需向下滚动即可看到字母的变化。

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

12 个答案:

答案 0 :(得分:191)

How do I remove diacritics (accents) from a string in .NET?

重新发布我的帖子

这种方法在java 中工作正常(纯粹是为了删除变音符号也称为重音符号)

它基本上将所有重音字符转换为deAccented对应字符,然后将它们组合为变音符号。现在你可以使用正则表达式去除变音符号。

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("");
}

答案 1 :(得分:70)

这是Apache Commons Lang的一部分。 3.0。

org.apache.commons.lang3.StringUtils.stripAccents("Añ");

返回An

另见http://www.drillio.com/en/software-development/java/removing-accents-diacritics-in-any-language/

答案 2 :(得分:19)

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

首先,您需要了解您尝试做的事情的局限性。正如其他人所指出的那样,变音符是有原因的:它们本质上是该语言字母表中的独特字母,具有自己的意义/声音等。删除这些标记与替换英语单词中的随机字母相同。这是在您考虑使用西里尔语和其他基于脚本的文本(如阿拉伯语)之前,这些文本根本无法“转换”为英语。

如果必须,无论出于何种原因,转换字符,那么唯一合理的方法就是首先减少手头任务的范围。考虑输入的来源 - 如果您正在为“西方世界”编写应用程序(使用与任何语言一样好的短语),那么您将不太可能需要解析阿拉伯字符。同样,Unicode字符集包含数百个数学和图形符号:用户没有(简单)方法直接输入这些符号,因此您可以假设它们可以被忽略。

通过采用这些逻辑步骤,您可以减少要解析的可能字符数,使基于字典的查找/替换操作成为可能。然后它变成了一些创建字典的轻微无聊的工作,以及执行替换的一个微不足道的任务。如果您的语言支持本机Unicode字符(正如Java那样)并正确地优化静态结构,那么查找和替换往往会非常快速。

这来自于为允许最终用户搜索包含变音字符的书目数据所需的应用程序的经验。查询数组(就像我们的情况一样)花了大约一个人的时间来制作,以涵盖所有西欧语言的所有变音符号。

答案 3 :(得分:16)

由于将“家庭”变成“tђєŦค3เℓy”的编码实际上是随机的,并且没有遵循任何可以通过所涉及的Unicode码点信息解释的算法,因此没有通用的方法来解决这个算法

您需要将Unicode字符的映射构建为类似的拉丁字符。您可以通过一些智能机器学习表示Unicode代码点的实际字形来完成此操作。但我认为这方面的努力将大于手动构建映射。特别是如果你有大量的例子可以用来构建你的映射。

澄清一下:实际上可以通过Unicode数据解决一些替换(正如其他答案所示),但有些字母与它们类似的拉丁字符没有任何合理的关联。

示例:

  • “ђ”(U + 0452 CYRILLIC SMALL LETTER DJE)与“d”更相关,而不是“h”,但用于表示“h”。
  • “Ŧ”(U + 0166 LATIN CAPITAL LETTER T WITH STROKE)与“T”(顾名思义)有些相关,但用于表示“F”。
  • “ค”(U + 0E04 THAI CHARACTER KHO KHWAI)完全与任何拉丁字符无关,在您的示例中用于表示“a”

答案 4 :(得分:7)

原始请求已经回答了。

但是,我正在为那些可能正在寻找通用音译代码的人发布以下答案,以便在Java中将任何字符集音译为拉丁语/英语。

音译的天真含义: 它的最终形式/目标字符集中的翻译字符串听起来像是原始形式的字符串。 如果我们想将任何字符集音译为拉丁语(英文字母),那么ICU4(java中的ICU4J库)就可以完成这项工作。

以下是java中的代码片段:

    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;
    }

答案 5 :(得分:6)

如果需要转换“òéışöç-> 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
    }
}

JDK 1.6提供了可用于此任务的java.text.Normalizer类。

查看示例here

答案 6 :(得分:6)

测试字符串:ÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝß

经过测试:

  • Apache Commons Lang3的输出:AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • ICU4j的输出:AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • JUnidecode的输出:AAAAAAECEEEEIIIIDNOOOOOOUUUUUss(与Ý和issue的问题)
  • Unidecode的输出:AAAAAAECEEEEIIIIDNOOOOOOUUUUYss

最后一个选择是最好的。

答案 7 :(得分:4)

将任意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...
}

答案 8 :(得分:4)

您可以尝试使用unidecoderuby gemperl module on cpan。从本质上讲,它可以作为一个巨大的查找表,每个unicode代码点与一个ascii字符或字符串相关。

答案 9 :(得分:4)

没有简单或一般的方法可以做你想要的事情,因为这些字母看起来像你想要转换的拉丁字母只是你的主观意见。它们实际上是单独的字母,具有各自独特的名称和声音,恰好看起来像一个拉丁字母。

如果您想进行转换,则必须根据您认为非拉丁字母应转换为的拉丁字母创建自己的翻译表。

(如果你只想删除变音符号,这个帖子中有一些答案:How do I remove diacritics (accents) from a string in .NET?但是你描述了一个更普遍的问题)

答案 10 :(得分:4)

我很晚才参加聚会,但今天面对这个问题后,我发现这个答案非常好:

String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD)
    .replaceAll("[^\\p{ASCII}]", "");

参考: https://stackoverflow.com/a/16283863

答案 11 :(得分:2)

以下课程可以解决问题:

org.apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter