如何删除Java中的代理字符?

我面临的情况是我在文本中获取Surrogate字符,我将保存到MySql 5.1。 由于此不支持UTF-16,我想在将其保存到数据库之前通过java方法手动删除这些代理对。

我现在已经编写了以下方法,我很想知道是否有一种直接和最佳的方法来处理这个问题。

在此先感谢您的帮助。

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)

    char值是代理代码单元,当且仅当它是低代理代码单元或高代理代码单元时。

  • 检查对似乎毫无意义,为什么不删除所有代理?

  • x == false等同于!x

  • 在不需要同步的情况下(如从不离开本地范围的变量), StringBuilder会更好。

我建议这个:

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

打破if语句

你问过这句话:

 if (!(Character.isHighSurrogate(c) || Character.isLowSurrogate(c))) { sb.append(firstChar); } 

理解它的一种方法是将每个操作分解为自己的function,这样你就可以看到组合符合你的期望:

 static boolean isSurrogate(char c) { return Character.isHighSurrogate(c) || Character.isLowSurrogate(c); } static boolean isNotSurrogate(char c) { return !isSurrogate(c); } ... if (isNotSurrogate(c)) { sb.append(firstChar); } 

Java字符串存储为16位字符序列,但它们代表的是unicode字符序列。 在unicode术语中,它们存储为代码单元,但是模型代码点。 因此,谈论删除代理人是没有意义的,代理人在字符/代码点表示中不存在(除非你有流氓单一代理人,在这种情况下你有其他问题)。

相反,你想要做的是删除任何在编码时需要代理的字符。 这意味着任何超出基本多语言平面的角色。 您可以使用简单的正则表达式执行此操作:

 return query.replaceAll("[^\u0000-\uffff]", ""); 

为什么不简单

 for (int i = 0; i < query.length(); i++) char c = query.charAt(i); if(!isHighSurrogate(c) && !isLowSurrogate(c)) sb.append(c); 

你可能应该用“?”代替它们,而不是用它们来替换它们。

只是好奇。 如果char是高代理人,是否需要检查下一个? 它应该是低代理人。 修改后的版本将是:

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

如果删除,所有这些解决方案都很有用,但如果重新使用,则下面更好

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