我使用以下链接创建key = unicode字符值的hashmap,value是它应该映射到的实际字符 - https://github.com/lmjabreu/solr-conftemplate/blob/master/mapping-ISOLatin1Accent.txt
到目前为止,我已经编写了以下代码来删除字符串
中的重音符号public class ACCENTS {
public static void main(String[] args){
// this is the hashmap that stores the mappings of the characters to their ascii equivalent
HashMap<Character, Character> characterMappings = new HashMap<>();
characterMappings.put('\u00C0', 'A');
characterMappings.put('\u00C1', 'A');
characterMappings.put('\u00C2', 'A');
characterMappings.put('\u00C3', 'A');
characterMappings.put('\u00C4', 'A');
characterMappings.put('\u00C5', 'A');
characterMappings.put('\u00C7','C');
characterMappings.put('\u00C8', 'E');
characterMappings.put('\u00C9','E');
characterMappings.put('\u00CA', 'E');
characterMappings.put('\u00CB', 'E');
characterMappings.put('\u00CC', 'I');
characterMappings.put('\u00CD', 'I');
characterMappings.put('\u00CE', 'I');
characterMappings.put('\u00CF', 'I');
characterMappings.put('\u00D0', 'D');
characterMappings.put('\u00D1', 'N');
characterMappings.put('\u00D2', 'O');
characterMappings.put('\u00D3', 'O');
characterMappings.put('\u00D4', 'O');
characterMappings.put('\u00D5', 'O');
characterMappings.put('\u00D6', 'O');
characterMappings.put('\u00D8', 'O');
characterMappings.put('\u00D9', 'U');
characterMappings.put('\u00DA', 'U');
characterMappings.put('\u00DB', 'U');
characterMappings.put('\u00DC', 'U');
characterMappings.put('\u00DD', 'Y');
characterMappings.put('\u0178', 'Y');
characterMappings.put('\u00E0', 'a');
characterMappings.put('\u00E1', 'a');
characterMappings.put('\u00E2', 'a');
characterMappings.put('\u00E3','a');
characterMappings.put('\u00E4', 'a');
characterMappings.put('\u00E5', 'a');
characterMappings.put('\u00E7', 'c');
characterMappings.put('\u00E8', 'e');
characterMappings.put('\u00E9', 'e');
characterMappings.put('\u00EA','e');
characterMappings.put('\u00EB', 'e');
characterMappings.put('\u00EC', 'i');
characterMappings.put('\u00ED', 'i');
characterMappings.put('\u00EE', 'i');
characterMappings.put('\u00EF', 'i');
characterMappings.put('\u00F0', 'd');
characterMappings.put('\u00F1','n' );
characterMappings.put('\u00F2', 'o');
characterMappings.put('\u00F3', 'o');
characterMappings.put('\u00F4', 'o');
characterMappings.put('\u00F5', 'o');
characterMappings.put('\u00F6', 'o');
characterMappings.put('\u00F8', 'o');
characterMappings.put('\u00F9', 'u');
characterMappings.put('\u00FA', 'u');
characterMappings.put('\u00FB', 'u');
characterMappings.put('\u00FC', 'u');
characterMappings.put('\u00FD', 'y');
characterMappings.put('\u00FF', 'y');
String token = "nа̀ра";
String newString = "";
for(int i = 0 ; i < token.length() ; ++i){
if( characterMappings.containsKey(token.charAt(i)) )
newString += characterMappings.get(token.charAt(i));
else
newString += token.charAt(i);
}
System.out.println(newString);
}
}
预期的结果应该是“napa”,但事实证明没有进行转换,这种情况可能导致偏离的原因,我无法找到。
答案 0 :(得分:5)
String s = "nа̀ра";
s = Normalizer.normalize( s, Normalizer.Form.NFD );
s = s.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
System.out.println( s );
- &GT;纳帕
(如果你坚持使用HashMap,你应该看看'Normalizer'类,因为它也可以在另一个方向工作。)
取自本文:http://blog.smartkey.co.uk/2009/10/how-to-strip-accents-from-strings-using-java-6/
答案 1 :(得分:0)
你遇到了一些最丑陋的Java特性: 一个unicode字符可以用字符的tupel(甚至是tripel)来表示。
实际上,令牌的长度为5个字符。 á是两个字符的组合,只能表示为字符串。
这就是为什么
characterMappings.put('а̀`', 'y'); //(accent can't be displayed correctly in code-mode, try it yourself)
不会编译。
Here是一个更多的解释。
在我的拙见中,String是Java中最糟糕的类之一。特别是如果你使用'非标准'字符。
要解决您的问题,我建议您将地图更改为Map<String,String>
或Map<String,Character>
。通过这种方式,您可以映射“角色”,并且如果您关闭转义的unicode字符,则代码会变得更易读,从而使代码变得更加可读。
有关Google的HighSurrogate或CodePoint的更多信息。 CodePoints是有效的(=可显示的)字符序列,如前所述,它不一定与字符串中的字符数相对应。
这是必要的,因为Java-Character只有2个字节宽。要小于所有unicode字符,但大部分时间 (=只要你使用标准拉丁字符)。
修改强>
即使使用Map<String,String>
,您的代码也无法正常工作,因为您仍会循环使用字符。但是没有一个Java字符能与你匹配特殊的unicode字符。
这可能会有所帮助,虽然它在任何情况下都可能无效(java字符串毕竟是令人讨厌的):
HashMap<String, String> characterMappings = new HashMap<>();
characterMappings.put("а̀", "a");
String token = "nа̀ра";
String newString = "";
for (Entry<String, String> e : characterMappings.entrySet()) {
token = token.replaceAll(e.getKey(), e.getValue());
}
System.out.println(token);
修改2
由于将代码发布为评论很糟糕:
String s = "brûlée";
String s1 = Normalizer.normalize(s, Normalizer.Form.NFKD);
String regex = "[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+";
String s2 = new String(s1.replaceAll(regex, "").getBytes("ascii"),
"ascii");
System.out.println(s2);
这对我来说对我来说很有用。 @Scheintod仍然值得赞扬。找到来源here
祝你好运
SAM