除了使用String.replaceAll()
方法并逐个替换字母外,是否有更好的方法来去除重音并使这些字母规范化?
例如:
输入:orčpžsíáýd
输出:orcpzsiayd
它不需要包括所有带重音符号的字母,如俄语或中文字母。
除了使用String.replaceAll()
方法并逐个替换字母外,是否有更好的方法来去除重音并使这些字母规范化?
例如:
输入:orčpžsíáýd
输出:orcpzsiayd
它不需要包括所有带重音符号的字母,如俄语或中文字母。
@David Conrad的解决方案是我尝试过的最快的,但它确实有一个bug。它基本上会剥离掉不是重音符号的字符,例如中文字符和其他字母如æ都被剥离了。 我们想要剥离的字符是非间隔标记,即在最终字符串中不占用额外宽度的字符。这些零宽度字符基本上会与其他字符组合在一起。如果你能看到它们单独作为一个字符,例如像这样',我猜测它是与空格字符结合在一起的。
public static String flattenToAscii(String string) {
char[] out = new char[string.length()];
String norm = Normalizer.normalize(string, Normalizer.Form.NFD);
int j = 0;
for (int i = 0, n = norm.length(); i < n; ++i) {
char c = norm.charAt(i);
int type = Character.getType(c);
//Log.d(TAG,""+c);
//by Ricardo, modified the character check for accents, ref: https://dev59.com/12025IYBdhLWcg3w96wW#5697575
if (type != Character.NON_SPACING_MARK){
out[j] = c;
j++;
}
}
//Log.d(TAG,"normalized string:"+norm+"/"+new String(out));
return new String(out);
}
遇到了同样的问题,这里提供使用 Kotlin 扩展的解决方案
val String.stripAccents: String
get() = Regex("\\p{InCombiningDiacriticalMarks}+")
.replace(
Normalizer.normalize(this, Normalizer.Form.NFD),
""
)
用法
val textWithoutAccents = "some accented string".stripAccents
一种更快、更安全的方式
public static String removeDiacritics(String str) {
if (str == null)
return null;
if (str.isEmpty())
return "";
int len = str.length();
StringBuilder sb
= new StringBuilder(len);
//iterate string codepoints
for (int i = 0; i < len; ) {
int codePoint = str.codePointAt(i);
int charCount
= Character.charCount(codePoint);
if (charCount > 1) {
for (int j = 0; j < charCount; j++)
sb.append(str.charAt(i + j));
i += charCount;
continue;
}
else if (codePoint <= 127) {
sb.append((char)codePoint);
i++;
continue;
}
sb.append(
java.text.Normalizer
.normalize(
Character.toString((char)codePoint),
java.text.Normalizer.Form.NFD)
.charAt(0));
i++;
}
return sb.toString();
}
我认为最好的解决方案是将每个字符转换为十六进制,并用另一个十六进制替换它。这是因为有两种Unicode输入法:
Composite Unicode
Precomposed Unicode
In Composite Unicode, "Ồ" is combined from 2 char: Ô (U+00d4) and ̀ (U+0300)
In Precomposed Unicode, "Ồ" is single char (U+1ED2)
我曾为一些银行开发了这个功能,以便在将信息发送到核心银行之前进行转换(通常不支持Unicode),但当最终用户使用多种Unicode输入方式输入数据时,我遇到了这个问题。因此,我认为将其转换为十六进制并进行替换是最可靠的方法。
如果有人在Kotlin中遇到困难,这段代码非常好用。为了避免不一致性,我还使用了.toUpperCase和Trim()。然后我将此函数转换:
fun stripAccents(s: String):String{
if (s == null) {
return "";
}
val chars: CharArray = s.toCharArray()
var sb = StringBuilder(s)
var cont: Int = 0
while (chars.size > cont) {
var c: kotlin.Char
c = chars[cont]
var c2:String = c.toString()
//these are my needs, in case you need to convert other accents just Add new entries aqui
c2 = c2.replace("Ã", "A")
c2 = c2.replace("Õ", "O")
c2 = c2.replace("Ç", "C")
c2 = c2.replace("Á", "A")
c2 = c2.replace("Ó", "O")
c2 = c2.replace("Ê", "E")
c2 = c2.replace("É", "E")
c2 = c2.replace("Ú", "U")
c = c2.single()
sb.setCharAt(cont, c)
cont++
}
return sb.toString()
}
要使用这些函数,请像这样转换代码:
var str: String
str = editText.text.toString() //get the text from EditText
str = str.toUpperCase().trim()
str = stripAccents(str) //call the function