【问题标题】:How to remove surrogate characters in Java?如何删除Java中的代理字符?
【发布时间】:2012-10-03 17:41:48
【问题描述】:

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

【问题讨论】:

  • 你说得对,布伦丹。我会修改。除此之外,您还有什么好的方法可以删除代理?

标签: java string surrogate-pairs


【解决方案1】:

这里有几件事:

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

理解它的一种方法是将每个操作分解成它自己的函数,这样你就可以看到这个组合达到了你的预期:

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

【讨论】:

  • 我使用的是 Jdk 1.6.0。而且我找不到内置的 Character.isSurrogate(c) 方法。那是现有的还是你举的例子?
  • @Slowcoder 显然它是在 Java 7 中添加的。我切换到在 Java 6 中工作的版本。您可以将声明阅读为“不是高代理或低代理”而不是(更多在我看来很复杂)“不是高代理,也不是低代理”。
  • 如果 "c" 是低代理字符,由于 OR 条件,此代码会将字符附加到 "sb"。我说的对吗?
  • @Slowcoder 不,检查括号。如果isLowSurrogate(c)为真,那么isHighSurrogate(c) || isLowSurrogate(c)(因为x || true为真),所以!(isHighSurrogate(c) || isLowSurrogate(c))为假,所以不会追加。如果这太令人困惑,请随意使用其他版本,但我建议学习如何处理复杂的逻辑语句,因为它们有时会出现(我参加了逻辑课程作为我的部分哲学学分,它非常有用)。
  • 我添加了一个功能分解,每个步骤都很简单。当逻辑语句变得太复杂而无法理解时,我建议这样做。
【解决方案2】:

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

相反,您要做的是删除编码时需要代理的任何字符。这意味着任何超出基本多语言平面的字符。你可以用一个简单的正则表达式来做到这一点:

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

【讨论】:

  • 它有帮助。感谢您的回复,汤姆。
【解决方案3】:

为什么不简单

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

您可能应该将它们替换为“?”,而不是直接删除它们。

【讨论】:

  • 真的很有帮助,谢谢。因此,我假设按每个字符进行迭代是删除它们的唯一方法,并且没有直接的方法可以获取字符串作为参数并返回删除了代理项的字符串。我说的对吗?
  • JDK中不存在这种方法。
【解决方案4】:

只是好奇。如果 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();
}

【讨论】:

    【解决方案5】:

    如果删除,所有这些解决方案都是有用的 但是如果repalce,下面会更好

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-30
      • 2021-03-17
      • 2017-10-30
      • 1970-01-01
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多