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


问题内容

我正面临一种情况,我在保存到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();
}

问题答案:

这里有几件事:

当且仅当它是低代理代码单元或高代理代码单元时,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);
}

理解它的一种方法是将每个操作分解为自己的功能,因此您可以看到该组合可以实现您的期望:

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