iOS 5.0之前,蘋果都是採用3個字節來承接 emoji 表情,Java 的普通 char 可以支持顯示。但 iOS 5.0 之後, 蘋果升級了系統自帶的 emoji 表情輸入法,用的 Unicode 6 標準來統一,是採用4個 bytes 來承接一個 emoji 表情。如果不做處理的話,這種表情直接存儲到 mysql5.5 以下的數據庫是會報錯的。就像這兩個表情一樣:口口, 在 Windows 8 以下估計都不支持顯示,可能會顯示成框框,可能壓根就是空白, 你可以在
Mac 中使用Safari 瀏覽器中,就可以看到。經過測試,在 Mac 就算用 Chrome 瀏覽器(Version 25.0.1364.172)也是不行的。
這種數據在 Mysql 5.5 之前,UTF-8 支持1-3個字節的編碼,從 Mysql5.5 開始後,可以支持4個字節的 UTF 編碼,但要特殊標記。修改 Mysql 相應存儲字段爲 utf8mb4 。修改語句如下:
2 |
MODIFY
COLUMN content varchar (500)
CHARACTER |
3 |
SET
utf8mb4 COLLATE
utf8mb4_unicode_ci |
4 |
DEFAULT
NULL COMMENT 'content of message' ; |
在某種業務情景下,我們可以選擇過濾掉這種“非法”的字符。我採用的方式是,在字符上面做操作,下面是Java示例代碼,核心的代碼附上,應該是 無法直接下載就能夠編譯,你得小小的做一些微調,沒有額外的依賴:
01 |
public class
EmojiFilter { |
08 |
public
static boolean
containsEmoji(String source) { |
09 |
if
(StringUtils.isBlank(source)) { |
13 |
int
len = source.length(); |
15 |
for
( int
i = 0 ; i < len; i++) { |
16 |
char
codePoint = source.charAt(i); |
18 |
if
(isEmojiCharacter(codePoint)) { |
27 |
private
static boolean
isEmojiCharacter( char codePoint) { |
28 |
return
(codePoint == 0x0 ) || |
32 |
((codePoint >=
0x20 ) && (codePoint <=
0xD7FF )) || |
33 |
((codePoint >=
0xE000 ) && (codePoint <=
0xFFFD )) || |
34 |
((codePoint >=
0x10000 ) && (codePoint <=
0x10FFFF )); |
38 |
* 過濾emoji 或者 其他非文字類型的字符 |
42 |
public
static String filterEmoji(String source) { |
44 |
if
(!containsEmoji(source)) { |
48 |
StringBuilder buf =
null ; |
50 |
int
len = source.length(); |
52 |
for
( int
i = 0 ; i < len; i++) { |
53 |
char
codePoint = source.charAt(i); |
55 |
if
(isEmojiCharacter(codePoint)) { |
57 |
buf =
new StringBuilder(source.length()); |
60 |
buf.append(codePoint); |
68 |
if
(buf.length() == len) { |
72 |
return
buf.toString(); |
還有優化的空間,但是已經能夠滿足大多數情況的需求,附上單元測試(JUnit4):
01 |
public class
EmojiFilterTest { |
08 |
public
void fileterEmoji() { |
09 |
String s =
"<body>口口213這是一個有各種內容的消息, Hia Hia Hia !!!! xxxx@@@...*)!"
+ |
10 |
"(@*$&@(&#!)@*)!&$!)@^%@(!&#. 口口口], " ; |
11 |
String c = Utils.filterEmoji(s); |
12 |
assertFalse(s.equals(c)); |
13 |
String expected =
"<body>213這是一個有各種內容的消息, Hia Hia Hia !!!! xxxx@@@...*)"
+ |
14 |
"!(@*$&@(&#!)@*)!&$!)@^%@(!&#. ], " ; |
15 |
assertEquals(expected, c); |
17 |
assertSame(expected,
"<body>213這是一個有各種內容的消息, Hia Hia Hia !!!! xxxx@@@...*)"
+ |
18 |
"!(@*$&@(&#!)@*)!&$!)@^%@(!&#. ], " ); |
19 |
assertSame(c, Utils.filterEmoji(c)); |
原文鏈接:http://doombyte.com/blog/2013/03/20/filter-emoji-emotion-in-string/