从字符串中删除重音符号

Posted

技术标签:

【中文标题】从字符串中删除重音符号【英文标题】:Remove accents from String 【发布时间】:2012-01-21 08:35:26 【问题描述】:

android 中是否有任何方法(据我所知)没有 java.text.Normalizer,可以从字符串中删除任何重音。例如“éàù”变成“eau”。

如果可能的话,我想避免解析字符串来检查每个字符!

【问题讨论】:

Android 从 API 级别 9 开始具有java.text.Normalizer,如果您正在使用它(或更高版本)。 ***.com/questions/6328654/…的可能重复 如果是排序或匹配,看Collator;除非您需要显示结果,否则这比自己剥离重音要好。 【参考方案1】:

java.text.Normalizer 在 Android 中(无论如何都是最新版本)。你可以使用它。

EDIT供参考,这里是如何使用Normalizer

string = Normalizer.normalize(string, Normalizer.Form.NFD);
string = string.replaceAll("[^\\pASCII]", "");

(从下面的 cmets 中的链接粘贴)

【讨论】:

我正在尝试使用 API 级别 7 进行编码以与旧设备兼容,但我认为它不存在 您能否发布一个示例,说明如何调用Normalizer.normalize 来删除重音? @Johann 添加到 API-9 developer.android.com/reference/java/text/Normalizer.html @Guillaume,嗨,我来自波兰,它不能使用“Ł”:s 好吧,这确实会从字符串中去除所有非拉丁语,而不仅仅是重音。【参考方案2】:

我已经根据我的需要调整了 Rabi 的解决方案,希望对某人有所帮助:

private static Map<Character, Character> MAP_NORM;
public static String removeAccents(String value)

    if (MAP_NORM == null || MAP_NORM.size() == 0)
    
        MAP_NORM = new HashMap<Character, Character>();
        MAP_NORM.put('À', 'A');
        MAP_NORM.put('Á', 'A');
        MAP_NORM.put('Â', 'A');
        MAP_NORM.put('Ã', 'A');
        MAP_NORM.put('Ä', 'A');
        MAP_NORM.put('È', 'E');
        MAP_NORM.put('É', 'E');
        MAP_NORM.put('Ê', 'E');
        MAP_NORM.put('Ë', 'E');
        MAP_NORM.put('Í', 'I');
        MAP_NORM.put('Ì', 'I');
        MAP_NORM.put('Î', 'I');
        MAP_NORM.put('Ï', 'I');
        MAP_NORM.put('Ù', 'U');
        MAP_NORM.put('Ú', 'U');
        MAP_NORM.put('Û', 'U');
        MAP_NORM.put('Ü', 'U');
        MAP_NORM.put('Ò', 'O');
        MAP_NORM.put('Ó', 'O');
        MAP_NORM.put('Ô', 'O');
        MAP_NORM.put('Õ', 'O');
        MAP_NORM.put('Ö', 'O');
        MAP_NORM.put('Ñ', 'N');
        MAP_NORM.put('Ç', 'C');
        MAP_NORM.put('ª', 'A');
        MAP_NORM.put('º', 'O');
        MAP_NORM.put('§', 'S');
        MAP_NORM.put('³', '3');
        MAP_NORM.put('²', '2');
        MAP_NORM.put('¹', '1');
        MAP_NORM.put('à', 'a');
        MAP_NORM.put('á', 'a');
        MAP_NORM.put('â', 'a');
        MAP_NORM.put('ã', 'a');
        MAP_NORM.put('ä', 'a');
        MAP_NORM.put('è', 'e');
        MAP_NORM.put('é', 'e');
        MAP_NORM.put('ê', 'e');
        MAP_NORM.put('ë', 'e');
        MAP_NORM.put('í', 'i');
        MAP_NORM.put('ì', 'i');
        MAP_NORM.put('î', 'i');
        MAP_NORM.put('ï', 'i');
        MAP_NORM.put('ù', 'u');
        MAP_NORM.put('ú', 'u');
        MAP_NORM.put('û', 'u');
        MAP_NORM.put('ü', 'u');
        MAP_NORM.put('ò', 'o');
        MAP_NORM.put('ó', 'o');
        MAP_NORM.put('ô', 'o');
        MAP_NORM.put('õ', 'o');
        MAP_NORM.put('ö', 'o');
        MAP_NORM.put('ñ', 'n');
        MAP_NORM.put('ç', 'c');
    

    if (value == null) 
        return "";
    

    StringBuilder sb = new StringBuilder(value);

    for(int i = 0; i < value.length(); i++) 
        Character c = MAP_NORM.get(sb.charAt(i));
        if(c != null) 
            sb.setCharAt(i, c.charValue());
        
    

    return sb.toString();


【讨论】:

这里有更多波兰变音符号的转换: MAP_NORM.put('Ą' to 'A'); MAP_NORM.put('Ę' to 'E'); MAP_NORM.put('Ć' 到 'C'); MAP_NORM.put('Ł' to 'L'); MAP_NORM.put('Ń' to 'N'); MAP_NORM.put('Ś' to 'S'); MAP_NORM.put('Ź' to 'Z'); MAP_NORM.put('Ż' to 'Z'); MAP_NORM.put('±' to 'a'); MAP_NORM.put('ę' to 'e'); MAP_NORM.put('ç' 到 'c'); MAP_NORM.put('ć' to 'c'); MAP_NORM.put('ł' 到 'l'); MAP_NORM.put('ń' 到 'n'); MAP_NORM.put('ś' to 's'); MAP_NORM.put('ź' to 'z'); MAP_NORM.put('ż' to 'z');【参考方案3】:

这可能不是最有效的解决方案,但它可以解决问题并且适用于所有 Android 版本:

private static Map<Character, Character> MAP_NORM;
static  // Greek characters normalization
    MAP_NORM = new HashMap<Character, Character>();
    MAP_NORM.put('ά', 'α');
    MAP_NORM.put('έ', 'ε');
    MAP_NORM.put('ί', 'ι');
    MAP_NORM.put('ό', 'ο');
    MAP_NORM.put('ύ', 'υ');
    MAP_NORM.put('ή', 'η');
    MAP_NORM.put('ς', 'σ');
    MAP_NORM.put('ώ', 'ω');
    MAP_NORM.put('Ά', 'α');
    MAP_NORM.put('Έ', 'ε');
    MAP_NORM.put('Ί', 'ι');
    MAP_NORM.put('Ό', 'ο');
    MAP_NORM.put('Ύ', 'υ');
    MAP_NORM.put('Ή', 'η');
    MAP_NORM.put('Ώ', 'ω');


public static String removeAccents(String s) 
    if (s == null) 
        return null;
    
    StringBuilder sb = new StringBuilder(s);

    for(int i = 0; i < s.length(); i++) 
        Character c = MAP_NORM.get(sb.charAt(i));
        if(c != null) 
            sb.setCharAt(i, c.charValue());
        
    

    return sb.toString();

【讨论】:

【参考方案4】:

虽然 Guillaume 的回答确实有效,但它会从字符串中删除 all 非 ASCII 字符。如果您希望保留这些代码,请尝试以下代码(string 是要简化的字符串):

// Convert input string to decomposed Unicode (NFD) so that the
// diacritical marks used in many European scripts (such as the
// "C WITH CIRCUMFLEX" → ĉ) become separate characters.
// Also use compatibility decomposition (K) so that characters,
// that have the exact same meaning as one or more other
// characters (such as "㎏" → "kg" or "ヒ" → "ヒ"), match when
// comparing them.
string = Normalizer.normalize(string, Normalizer.Form.NFKD);

StringBuilder result = new StringBuilder();

int offset = 0, strLen = string.length();
while(offset < strLen) 
    int character = string.codePointAt(offset);
    offset += Character.charCount(character);

    // Only process characters that are not combining Unicode
    // characters. This way all the decomposed diacritical marks
    // (and some other not-that-important modifiers), that were
    // part of the original string or produced by the NFKD
    // normalizer above, disappear.
    switch(Character.getType(character)) 
        case Character.NON_SPACING_MARK:
        case Character.COMBINING_SPACING_MARK:
            // Some combining character found
        break;

        default:
            result.appendCodePoint(Character.toLowerCase(character));
    


// Since we stripped all combining Unicode characters in the
// previous while-loop there should be no combining character
// remaining in the string and the composed and decomposed
// versions of the string should be equivalent. This also means
// we do not need to convert the string back to composed Unicode
// before returning it.
return result.toString();

【讨论】:

当然可以。如果要保留大写字母,请使用 result.appendCodePoint(character); 而不是 result.appendCodePoint(Character.toLowerCase(character));。 ;-)【参考方案5】:

所有重音字符都在扩展的 ASCII 字符代码集中,十进制值大于 127。因此您可以枚举字符串中的所有字符,如果十进制字符代码值大于 127,则将其映射回您想要的相等的。没有简单的方法将重音字符映射回非重音字符 - 您必须在内存中保留某种映射才能将扩展的十进制代码映射回非重音字符。

【讨论】:

以上是关于从字符串中删除重音符号的主要内容,如果未能解决你的问题,请参考以下文章

从字符串中删除重音符号

如何从 .NET 中的字符串中删除变音符号(重音符号)?

如何从 .NET 中的字符串中删除变音符号(重音符号)?

在 JavaScript 中删除字符串中的重音符号/变音符号

删除 mysql 查询中字符串字段的重音符号

R- 删除字符串中的重音符号