从字符串中删除非 ASCII 不可打印的字符

2022-09-02 02:10:09

我收到的用户输入包括非 ASCII 字符和不可打印字符,例如

\xc2d
\xa0
\xe7
\xc3\ufffdd
\xc3\ufffdd
\xc2\xa0
\xc3\xa7
\xa0\xa0

例如:

email : abc@gmail.com\xa0\xa0
street : 123 Main St.\xc2\xa0

所需输出:

  email : abc@gmail.com
  street : 123 Main St.

使用Java删除它们的最佳方法是什么?
我尝试了以下方法,但似乎不起作用

public static void main(String args[]) throws UnsupportedEncodingException {
        String s = "abc@gmail\\xe9.com";
        String email = "abc@gmail.com\\xa0\\xa0";

        System.out.println(s.replaceAll("\\P{Print}", ""));
        System.out.println(email.replaceAll("\\P{Print}", ""));
    }

输出

abc@gmail\xe9.com
abc@gmail.com\xa0\xa0

答案 1

您的要求不清楚。Java中的所有字符都是Unicode字符,因此,如果删除它们,将留下一个空字符串。我假设你的意思是你想删除任何非ASCII,不可打印的字符。String

String clean = str.replaceAll("\\P{Print}", "");

此处,表示可打印 ASCII 字符的 POSIX 字符类,而 是该类的补充。使用此表达式,所有不可打印 ASCII 的字符都将替换为空字符串。(额外的反斜杠是因为在字符串文本中启动转义序列。\p{Print}\P{Print}\


显然,所有输入字符实际上都是 ASCII 字符,表示不可打印或非 ASCII 字符的可打印编码。Mongo对这些字符串应该没有任何问题,因为它们只包含普通的可打印ASCII字符。

这一切对我来说听起来有点可疑。我相信正在发生的是,数据确实包含不可打印和非ASCII字符,而另一个组件(如日志记录框架)正在用可打印的表示形式替换这些字符。在简单测试中,您无法将可打印的表示形式转换回原始字符串,因此您错误地认为第一个正则表达式不起作用。

这是我的猜测,但是如果我误读了这种情况,并且你真的需要去掉文字转义,你可以使用以下正则表达式来做到这一点。\xHH

String clean = str.replaceAll("\\\\x\\p{XDigit}{2}", "");

Pattern 类的 API 文档很好地列出了 Java 正则表达式库支持的所有语法。为了更详细地阐述所有语法的含义,我发现 Regular-Expressions.info 网站非常有帮助。


答案 2

使用Google GuavaCharMatcher,您可以删除任何不可打印的字符,然后保留所有ASCII字符(删除任何重音符号),如下所示:

String printable = CharMatcher.INVISIBLE.removeFrom(input);
String clean = CharMatcher.ASCII.retainFrom(printable);

不确定这是否是你真正想要的,但它会删除问题示例数据中以转义序列表示的任何内容。


推荐