過濾字串中的Emoji表情
阿新 • • 發佈:2019-01-12
iOS 5.0之前,蘋果都是採用3個位元組來承接 emoji 表情,Java 的普通 char 可以支援顯示。但 iOS 5.0 之後, 蘋果升級了系統自帶的 emoji 表情輸入法,用的 Unicode 6 標準來統一,是採用4個 bytes 來承接一個 emoji 表情。如果不做處理的話,這種表情直接儲存到 mysql5.5 以下的資料庫是會報錯的。就像這兩個表情一樣:口口, 在 Windows 8 以下估計都不支援顯示,可能會顯示成框框,可能壓根就是空白, 你可以在 Mac 中
這種資料在 Mysql 5.5 之前,UTF-8 支援1-3個位元組的編碼,從 Mysql5.5 開始後,可以支援4個位元組的 UTF 編碼,但要特殊標記。修改 Mysql 相應儲存欄位為 utf8mb4 。修改語句如下:
1 |
ALTER TABLE table_name |
2 |
MODIFY COLUMN content varchar (500) CHARACTER |
3 |
SET utf8mb4 COLLATE utf8mb4_unicode_ci |
4 |
DEFAULT NULL COMMENT 'content of message' ; |
01 |
public class EmojiFilter { |
02 |
03 |
/** |
04 |
* 檢測是否有emoji字元 |
05 |
* @param source |
06 |
* @return 一旦含有就丟擲 |
07 |
*/ |
08 |
public static boolean containsEmoji(String source) { |
09 |
if (StringUtils.isBlank(source)) { |
10 |
return false ; |
11 |
} |
12 |
13 |
int len = source.length(); |
14 |
15 |
for ( int i = 0 ; i < len; i++) { |
16 |
char codePoint = source.charAt(i); |
17 |
18 |
if (isEmojiCharacter(codePoint)) { |
19 |
//do nothing,判斷到了這裡表明,確認有表情字元 |
20 |
return true ; |
21 |
} |
22 |
} |
23 |
24 |
return false ; |
25 |
} |
26 |
27 |
private static boolean isEmojiCharacter( char codePoint) { |
28 |
return (codePoint == 0x0 ) || |
29 |
(codePoint == 0x9 ) || |
30 |
(codePoint == 0xA ) || |
31 |
(codePoint == 0xD ) || |
32 |
((codePoint >= 0x20 ) && (codePoint <= 0xD7FF )) || |
33 |
((codePoint >= 0xE000 ) && (codePoint <= 0xFFFD )) || |
34 |
((codePoint >= 0x10000 ) && (codePoint <= 0x10FFFF )); |
35 |
} |
36 |
37 |
/** |
38 |
* 過濾emoji 或者 其他非文字型別的字元 |
39 |
* @param source |
40 |
* @return |
41 |
*/ |
42 |
public static String filterEmoji(String source) { |
43 |
44 |
if (!containsEmoji(source)) { |
45 |
return source; //如果不包含,直接返回 |
46 |
} |
47 |
//到這裡鐵定包含 |
48 |
StringBuilder buf = null ; |
49 |
50 |
int len = source.length(); |
51 |
52 |
for ( int i = 0 ; i < len; i++) { |
53 |
char codePoint = source.charAt(i); |
54 |
55 |
if (isEmojiCharacter(codePoint)) { |
56 |
if (buf == null ) { |
57 |
buf = new StringBuilder(source.length()); |
58 |
} |
59 |
60 |
buf.append(codePoint); |
61 |
} else { |
62 |
} |
63 |
} |
64 |
65 |
if (buf == null ) { |
66 |
return source; //如果沒有找到 emoji表情,則返回源字串 |
67 |
} else { |
68 |
if (buf.length() == len) { //這裡的意義在於儘可能少的toString,因為會重新生成字串 |
69 |
buf = null ; |
70 |
return source; |
71 |
} else { |
72 |
return buf.toString(); |
73 |
} |
74 |
} |
75 |
76 |
} |
77 |
} |
還有優化的空間,但是已經能夠滿足大多數情況的需求,附上單元測試(JUnit4):
01 |
public class EmojiFilterTest { |
02 |
03 |
04 |
/** |
05 |
* 測試emoji表情 |
06 |
*/ |
07 |
@Test |
08 |
public void fileterEmoji() { |
09 |
String s = "<body>口口213這是一個有各種內容的訊息, Hia Hia Hia !!!! [email protected]@@...*)!" + |
10 |
"(@*$&@(&#!)@*)!&$!)@^%@(!&#. 口口口], " ; |
11 |
String c = Utils.filterEmoji(s); |
12 |
assertFalse(s.equals(c)); |
13 |
String expected = "<body>213這是一個有各種內容的訊息, Hia Hia Hia !!!! [email protected]@@...*)" + |
14 |
"!(@*$&@(&#!)@*)!&$!)@^%@(!&#. ], " ; |
15 |
assertEquals(expected, c); |
16 |
// assertSame(c, expected); |
17 |
assertSame(expected, "<body>213這是一個有各種內容的訊息, Hia Hia Hia !!!! [email protected]@@...*)" + |
18 |
"!(@*$&@(&#!)@*)!&$!)@^%@(!&#. ], " ); |
19 |
assertSame(c, Utils.filterEmoji(c)); |
20 |
} |
21 |
22 |
} |
原文連結:http://doombyte.com/blog/2013/03/20/filter-emoji-emotion-in-string/