4-23
現在無論原生還是網頁端,表情符號絕大部分都可以正常顯示,但是也有一部分是不能正常顯示的。但存入到mysql的時候,不能夠正常顯示的表情符號,就會讓mysql(utf-8)拜拜了。這個不僅僅是顯示問題,很重要的一點是,會讓絕大部分玩家的游戲記錄被無情抹去,無法記錄。
先舉兩個例子:
微信名: base64加密后:8J+Xrw==
微信名: base64加密后:4pmj
第一個名字,算是一個比較新的表情符號,我參考了TX的游戲,
在王者榮耀上面,在S10賽季前,這個表情符號是用兩個特殊字符來表現的(忘了截圖),大概就是這樣的吧
,而S11賽季更新之后就變成這樣顯示了
,而且,以前的表情符號在王者榮耀里面是可以輸入的,現在已經禁止輸入表情
符號了,現在統一由這個字符代表表情符號。
表情符號的處理還有待改進呀
占2個字節的:帶有附加符號的拉丁文、希臘文、西里爾字母、亞美尼亞語、希伯來文、阿拉伯文、
敘利亞文及它拿字母則需要二個字節編碼
占3個字節的:基本等同於GBK,含21000多個漢字
占4個字節的:中日韓超大字符集里面的漢字,有5萬多個
再來看看這個表情符號的base64解碼,能夠正常顯示
但是這個就掛了,完全顯示不出來
下面就來看看,解密后他是個什么東西
不能正常顯示的表情符號解密后長度為2,能正常顯示的就是1
再來看看他們的Unicode編碼(charCodeAt() 方法可返回指定位置的字符的 Unicode 編碼。這個返回值是 0 - 65535 之間的整數),看起來也沒什么大的區別。但是長度卻不同,UTF-8編碼有可能是兩個、三個、四個字節,Emoji表情是4個字節,而MySQL的utf8編碼最多3個字節,所以數據插不進去,這就導致了數據腰斬的問題,數據都被這個不能插入的東西切成兩份了。
接下來翻查一下這兩個表情,
輸入55357(不顯示的表情的第一個字符),顯示如下:
長度為2的字符串(顯示不出來的表情符號),我們可以這樣理解,它里面有兩個字符(55357和56815),每一個字符轉出來有三個字符,長度達到了3,那就是55357這個字符占了9個字節 ,就是說他一個字符占位已經超出了3字節的長度了 (本人的理解下,只是猜測)。
輸入9827(♣),顯示如下:
以上是長度為1的字符串,我們可以這樣理解,那他占了3個字節,完全可以顯示和存儲在utf-8的數據結構里。
再看一下普通漢字的字節占位
也是可以顯示的。
來看看游戲數據庫里游戲記錄的數據結構:
Utf-8/不區分大小寫,可以,那樣這個結構就會被我那個表情搞死了。
很明顯,一些比較新的表情符號,是超過了3個字節的,所以就會出現類似以下的腰斬數據
, name的值和后面的數據已經被KO了,而這個問題不僅僅是影響使用這個名字的玩家,而是和他一起游戲過的玩家也會出現數據腰斬的情況,所以這個問題必須要解決。
在網上搜不到相關的文章,對特殊表情符號的處理而又是少之又少,沒什么有價值的參考的話,那就自己來一下吧,首先我可以想到的方案:
- 把特殊表情符號替換掉,或者屏蔽掉
- 看看能不能轉換一下編碼
- 看看能不能換一種加解密
第一種情況,體驗太不好了,在大廳明明能把表情顯示出來,但是戰績卻看不到?不行。第三種呢,貌似很大工程,這個以后在探討。比較適合的,簡便的應該是第二種了,直接在數據庫上面操作,好了,現在開始動數據庫吧。
我上網搜一下utf-8和utf-8mb4的區別,這個是肯定有詳細的文案可以查看的。
送上地址:http://blog.xieyc.com/utf8-and-utf8mb4/ 摘要:
二、為什么會有UTF8MB4?
既然utf8應付日常使用完全沒有問題,那為什么還要使用utf8mb4呢? 低版本的MySQL支持的utf8編碼,最大字符長度為 3 字節,如果遇到 4 字節的字符就會出現錯誤了。三個字節的 UTF-8 最大能編碼的 Unicode 字符是 0xFFFF,也就是 Unicode 中的基本多文平面(BMP)。也就是說,任何不在基本多文平面的 Unicode字符,都無法使用MySQL原有的 utf8 字符集存儲。這些不在BMP中的字符包括哪些呢?最常見的就是Emoji 表情(Emoji 是一種特殊的 Unicode 編碼,常見於 ios 和 android 手機上),和一些不常用的漢字,以及任何新增的 Unicode 字符等等。
三、擴展閱讀:UTF-8編碼
理論上將, UTF-8 格式使用一至六個字節,最大能編碼 31 位字符。最新的 UTF-8 規范只使用一到四個字節,最大能編碼21位,正好能夠表示所有的 17個 Unicode 平面。關於UTF編碼,請閱讀《常見編碼總結》一文。
而utf8 則是 Mysql 早期版本中支持的一種字符集,只支持最長三個字節的 UTF-8字符,也就是 Unicode 中的基本多文本平面。這可能是因為在MySQL發布初期,基本多文種平面之外的字符確實很少用到。而在MySQL5.5.3版本后,要在 Mysql 中保存 4 字節長度的 UTF-8 字符,就可以使用 utf8mb4 字符集了。例如可以用utf8mb4字符編碼直接存儲emoj表情,而不是存表情的替換字符。為了獲取更好的兼容性,應該總是使用 utf8mb4 而非 utf8,事實上,最新版的phpmyadmin默認字符集就是utf8mb4。誠然,對於 CHAR 類型數據,使用utf8mb4 存儲會多消耗一些空間
-----------------------------------------------------------------------------------------------
上面說的很清楚:utf8編碼,最大字符長度為 3 字節,如果遇到 4 字節的字符就會出現錯誤了。三個字節的 UTF-8 最大能編碼的 Unicode 字符是 0xFFFF,也就是 Unicode 中的基本多文平面(BMP)。也就是說,任何不在基本多文平面的 Unicode字符,都無法使用MySQL原有的 utf8 字符集存儲。這些不在BMP中的字符包括哪些呢?最常見的就是Emoji 表情。
這下就應該選對方案了,一切都是從打印出解密后的字符的長度引發的思考。