How to remove surrogate characters in Java?
我正面临这样一种情况:我在保存到MySQL5.1的文本中获取代理角色。由于UTF 16不支持这一点,所以我想在保存到数据库之前,用Java方法手动删除这些代理对。
我现在已经写了下面的方法,我很好奇是否有一个直接和最佳的方法来处理这个问题。
事先谢谢你的帮助。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public static String removeSurrogates(String query) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < query.length() - 1; i++) { char firstChar = query.charAt(i); char nextChar = query.charAt(i+1); if (Character.isSurrogatePair(firstChar, nextChar) == false) { sb.append(firstChar); } else { i++; } } if (Character.isHighSurrogate(query.charAt(query.length() - 1)) == false && Character.isLowSurrogate(query.charAt(query.length() - 1)) == false) { sb.append(query.charAt(query.length() - 1)); } return sb.toString(); } |
以下是一些事情:
Character.isSurrogate(char c) :
A char value is a surrogate code unit if and only if it is either a low-surrogate code unit or a high-surrogate code unit.
检查配对似乎毫无意义,为什么不直接删除所有代理呢?
x == false 相当于!x 。在不需要同步的情况下(像一个永远不会离开本地范围的变量),
StringBuilder 更好。
我建议:
1 2 3 4 5 6 7 8 9 10 11 | public static String removeSurrogates(String query) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < query.length(); i++) { char c = query.charAt(i); // !isSurrogate(c) in Java 7 if (!(Character.isHighSurrogate(c) || Character.isLowSurrogate(c))) { sb.append(firstChar); } } return sb.toString(); } |
分解
你问过这个声明:
理解它的一种方法是将每个操作分解成它自己的函数,这样您就可以看到组合执行您所期望的操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Java字符串存储为16位字符序列,但它们表示的是Unicode字符序列。在Unicode术语中,它们存储为代码单元,但为代码点建模。因此,讨论删除代理是没有意义的,因为它不存在于字符/代码点表示中(除非您有无赖的单个代理,在这种情况下,您还有其他问题)。
相反,您要做的是删除在编码时需要代理的任何字符。这意味着任何超出基本多语言平面的字符。您可以通过一个简单的正则表达式来实现这一点:
1 | return query.replaceAll("[^\u0000-\uffff]",""); |
为什么不简单
1 2 3 4 | for (int i = 0; i < query.length(); i++) char c = query.charAt(i); if(!isHighSurrogate(c) && !isLowSurrogate(c)) sb.append(c); |
您可能应该用"?"替换它们。而不是完全删除它们。
如果删除,所有这些解决方案都是有用的但如果再偿还,下面的就更好了
1 2 3 4 5 6 7 8 9 10 | StringBuffer sb = new StringBuffer(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if(Character.isHighSurrogate(c)){ sb.append('*'); }else if(!Character.isLowSurrogate(c)){ sb.append(c); } } return sb.toString(); |
只是好奇而已。如果char是high supergate,是否需要检查下一个?它应该是低代理。修改后的版本为:
1 2 3 4 5 6 7 8 9 10 11 | public static String removeSurrogates(String query) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < query.length(); i++) { char ch = query.charAt(i); if (Character.isHighSurrogate(ch)) i++;//skip the next char is it's supposed to be low surrogate else sb.append(ch); } return sb.toString(); } |