如何从Java字符串中删除控制字符?

40

我从UI获取了一个字符串,其中可能包含控制字符,我想要移除所有控制字符,但保留回车换行制表符

目前我找到两种方法可以移除所有控制字符:

1- 使用guava:

return CharMatcher.JAVA_ISO_CONTROL.removeFrom(string);

2- 使用正则表达式:

return string.replaceAll("\\p{Cntrl}", "");

4
所以你已经有了两种做法...你具体在问什么? - Jon Skeet
这就引出了一个问题,什么样的用户界面允许输入控制字符?也许你应该从源头上解决这个问题。 - Mr Lister
3
@Jon Skeet,以上两种方法都会将它们全部删除,我想删除除回车符、换行符和制表符以外的所有控制字符。 - Mahmoud Saleh
@MahmoudSaleh:啊,我现在明白了。 - Jon Skeet
2
你尝试过像这样的东西吗?return string.replaceAll("[\p{Cntrl}^\r\n\t]+", "");? - Andremoniy
1
请注意,CharMatcher.JAVA_ISO_CONTROL在Guava的后续版本中已被弃用。您可以使用CharMatcher.javaIsoControl()代替。 - Lorcan O'Neill
8个回答

31

如果您想删除其他或控制Unicode类别中的所有字符,可以像这样做。

System.out.println(
    "a\u0000b\u0007c\u008fd".replaceAll("\\p{Cc}", "")
); // abcd

注意:这实际上是从字符串中移除(其中包括)Unicode字符'\u008f',而不是转义形式的"%8F"字符串。

参考来源:polygenelubricants替换Unicode控制字符


2
这段代码并不能实现作者想要的功能,他还想保留换行、回车和制表符。上述代码会将它们全部删除。 - Krzysztof Krasoń
非常感谢!我花了一整天的时间在我的代码中寻找这个错误。Java中的Soap http请求返回http状态400,但是类似于soap-ui的测试环境或curl却可以正常工作,使用“相同”的请求xml。最后我发现了那些“看不见”的字符。 :) - csonuryilmaz
1
请至少用你自己的话来回答。 - ethanbustad

20

一种选择是使用CharMatcher的组合:

CharMatcher charsToPreserve = CharMatcher.anyOf("\r\n\t");
CharMatcher allButPreserved = charsToPreserve.negate();
CharMatcher controlCharactersToRemove = CharMatcher.JAVA_ISO_CONTROL.and(allButPreserved);

然后像以前一样使用removeFrom。我不知道它的效率如何,但至少很简单。


正如编辑中所指出的,Guava现在已经弃用了JAVA_ISO_CONTROL;更推荐使用javaIsoControl()方法。


CharMatcher.javaIsoControl() 现在已经被弃用,应使用 JAVA_ISO_CONTROL - Zon

14

这似乎是一个选项

    String s = "\u0001\t\r\n".replaceAll("[\\p{Cntrl}&&[^\r\n\t]]", "");
    for (char c : s.toCharArray()) {
        System.out.print((int) c + " ");
    }

打印出9 13 10,就像你所说的“除了回车、换行和制表符”。


9

使用这些

public static String removeNoneAscii(String str){
    return str.replaceAll("[^\\x00-\\x7F]", "");
}

public static String removeNonePrintable(String str){ // All Control Char
    return str.replaceAll("[\\p{C}]", "");
}

public static String removeOthersControlChar(String str){ // Some Control Char
    return str.replaceAll("[\\p{Cntrl}\\p{Cc}\\p{Cf}\\p{Co}\\p{Cn}]", "");
}

public static String removeAllControlChars(String str)
{
    return removeNonPrintable(str).replaceAll("[\\r\\n\\t]", "");
}

1
在Java正则表达式中,可以在字符类中排除一些字符。以下是一个示例程序,演示了类似的内容:
class test {
    public static void main (String argv[]) {
            String testStr="abcdefABCDEF";
            System.out.println(testStr);
            System.out.println(testStr.replaceAll("[\\p{Lower}&&[^cd]]",""));
    }
}

它将生成以下输出:

abcdefABCDEF
cdABCDEF

1
我正在使用Selenium测试网页界面。我使用Hamcrest断言和匹配器根据不同条件在页面源代码中搜索不同的字符串。
String pageSource = browser.getPageSource();
assertThat("Text not found!", pageSource, containsString(text));

使用IE或Firefox驱动程序可正常工作,但使用HtmlUnitDriver时会出现问题。HtmlUnitDriver将页面源代码格式化为制表符、换行符和其他控制字符。我使用了对Nidhish Krishnan的聪明答案进行改编。如果我直接使用Nidish的解决方案,则会留下额外的空格,因此我添加了一个名为filterTextForComparison的私有方法来过滤文本以进行比较。
String pageSource = filterTextForComparison(browser.getPageSource());
assertThat("Text not found!", pageSource, 
        containsString(filterTextForComparison(text)));

并且函数:

/**
 * Filter out any characters embedded in the text that will interfere with
 * comparing Strings.
 * 
 * @param text
 *            the text to filter.
 * @return the text with any extraneous character removed.
 */
private String filterTextForComparison(String text) {

    String filteredText = text;

    if (filteredText != null) {
        filteredText = filteredText.replaceAll("\\p{Cc}", " ").replaceAll("\\s{2,}", " ");
    }

    return filteredText;
}

首先,该方法将控制字符替换为一个空格,然后将多个空格替换为单个空格。我尝试使用"\p{Cc}+?"一次完成所有操作,但它未捕获"\t "变成" "的情况。

filteredText.replaceAll("\p{Cc}", " ").replaceAll("\s{2,}", " ") - 对我来说完美地运作了,谢谢! - Anandkumar

-1

-1
你可以使用Spring中的StringUtils:
String str = "\n\t\t\tsome text\t\t\n";
StringUtils.trimAllWhitespace(str); // some text

1
该问题要求删除控制字符,但排除空格控制字符;这个解决方案仅删除空格控制字符。此外,该解决方案还会删除空格字符,而空格字符通常不被视为控制字符。 - user9712582

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接