2012-06-13 185 views
11

我獲取用戶輸入包括Unicode字符,如的Java去除Unicode字符

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

例如:

email : [email protected]\xa0\xa0 
street : 123 Main St.\xc2\xa0 

所需的輸出:

email : [email protected] 
    street : 123 Main St. 

什麼是最好的方式將其移除使用Java?

更新:我嘗試以下,但似乎並沒有工作

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

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

輸出

[email protected]\xe9.com 
[email protected]\xa0\xa0 
+0

爲什麼要刪除它們? – jtahlborn

+1

@jtahlborn,Mongo無法序列化這些值 – daydreamer

回答

27

您的要求不明確。 Java String中的所有字符都是Unicode字符,因此如果刪除它們,則會留下空字符串。我假定你的意思是你想刪除任何非ASCII,不可打印的字符。

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

這裏,\p{Print}represents a POSIX character class用於打印的ASCII字符,而\P{Print}是一流的補充。有了這個表達式,所有而不是可打印的ASCII字符都被替換爲空字符串。 (額外反斜槓是因爲\開始在字符串文字的轉義序列。)


顯然,所有輸入的字符實際上是ASCII字符表示的非打印或非ASCII字符的可打印的編碼。 Mongo不應該對這些字符串有任何問題,因爲它們只包含普通的可打印ASCII字符。

這一切聽起來有點腥。我相信發生的事情是,數據確實包含不可打印和非ASCII字符,而另一個組件(如日誌框架)正在用可打印的表示來替換這些數據。在您的簡單測試中,您無法將可打印表示法翻譯回原始字符串,因此您錯誤地認爲第一個正則表達式不起作用。

這是我的猜測,但如果我誤讀了這種情況,而且確實需要刪除字面值\xHH轉義符,則可以使用以下正則表達式執行此操作。

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

Pattern類的API文檔中則列出了所有的Java的正則表達式庫支持的語法的一個好工作。有關所有語法的詳細說明,我發現Regular-Expressions.info site非常有幫助。

+0

這不起作用。可能是我做了一些不正確的事情,但不能正常工作 – daydreamer

+1

@daydreamer你能提供一個顯示什麼不起作用的[SSCCE](http://sscce.org/)嗎? – erickson

+0

public static void main(String args [])throws UnsupportedEncodingException {s}「abc @ gmail \\ xe9.com」; String email =「[email protected] \\ xa0 \\ xa0」; System.out.println(s.replaceAll(「\\ P {Print}」,「」)); System.out.println(email.replaceAll(「\\ P {Print}」,「」)); } 輸出 - abc @ gmail \ xe9.com [email protected] \ xa0 \ xa0 – daydreamer

1

您可以使用java.text.normalizer

2

你可以試試此代碼:

public String cleanInvalidCharacters(String in) { 
    StringBuilder out = new StringBuilder(); 
    char current; 
    if (in == null || ("".equals(in))) { 
     return ""; 
    } 
    for (int i = 0; i < in.length(); i++) { 
     current = in.charAt(i); 
     if ((current == 0x9) 
       || (current == 0xA) 
       || (current == 0xD) 
       || ((current >= 0x20) && (current <= 0xD7FF)) 
       || ((current >= 0xE000) && (current <= 0xFFFD)) 
       || ((current >= 0x10000) && (current <= 0x10FFFF))) { 
      out.append(current); 
     } 

    } 
    return out.toString().replaceAll("\\s", " "); 
} 

它適用於我從String刪除無效字符。

+3

這是很多神奇的數字。如何將這些子句(特別是範圍)提取到恰當命名的局部變量? –

10

隨着Google GuavaCharMatcher,您可以刪除任何non-printable字符,然後保留所有ASCII字符(將任何口音)是這樣的:

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

不知道如果這是你真正想要的,但它刪除任何東西在問題的示例數據中表示爲轉義序列。

+3

注意,INVISIBLE刪除了我認爲很奇怪的空格,因爲它確實是「可打印的」 –

7

我知道這也許較晚,但以供將來參考:

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

刪除所有非打印字符,但包括\n(換行),\t(標籤)和\r(回車),有時你想要保留這些角色。

對於這個問題使用反向邏輯:

String clean = str.replaceAll("[^\\n\\r\\t\\p{Print}]", ""); 
+0

Upvoted是因爲它在mongo-land中特別有用,可以防止外殼噴出大量非編碼的非ASCII字符(mongo確實更喜歡utf-8如果你想讓事情變得簡單) –

0

輸入=> 「 \ u7279 文本 \ u7279 就是我需要」 輸出=>「這段文字是我需要

如果您嘗試從上面的字符串中刪除Unicode字符,則此代碼將起作用

Pattern unicodeCharsPattern = Pattern.compile("\\\\u(\\p{XDigit}{4})"); 
Matcher unicodeMatcher = unicodeChars.matcher(data); 
String cleanData = null; 
if (unicodeMatcher.find()) { 
    cleanData = unicodeMatcher.replaceAll(""); 
}