微信消息推送之過長的文本消息拆分踩坑

場景提出

故事要從微信消息推送說起,因爲微信對文本消息的推送限定字節數爲2048個,多出來的直接被砍掉。所以就想要對過長的文本消息進行拆分。
起初想的是用字節數據拆分,但是發現用字節數組拆分,會出現消息轉化亂碼的問題,原因其實也很好理解,因爲不同字符佔用的字節數不一樣,所以簡單的拆分又重新轉換爲String,就會出現將本來一個字符的上半個字節轉換爲一個字符,下半個字節轉換爲一個字符,這樣就出現了亂碼。
因此,我決定按字符去拆分,但是按字符去拆分:(最終pageSize取600)

代碼示例

拆分方法(代碼片段):

public List<String> splitMessageByChars(String message,int pageSize) {
    List<String> messages = Lists.newArrayList();
    char[] chars = message.toCharArray();
    for (int i = 0;i<chars.length;i=i+pageSize){
        int j = i + pageSize;
        String m ;
        if (j>chars.length){
            m = new String(chars,i,chars.length-i);
        }else {
            m = new String(chars,i,pageSize);
        }
        if (m.indexOf('\n')==0){
            messages.add(m.substring(1));
        }else {
            messages.add(m);
        }
    }
    return messages;
}

可以看到代碼中對\n做了過濾,原因是微信的文本消息推送,如果你首字符爲\n的話就會報錯,所以就需要對消息首字符爲\n的情況做單獨處理。

字節數佔用的驗證(代碼片段)

@Test
public void contextLoads() throws UnsupportedEncodingException {
    List<String> charsets = Lists.newArrayList();
    charsets.add(StandardCharsets.UTF_8.name());
    charsets.add(StandardCharsets.UTF_16.name());
    charsets.add(StandardCharsets.UTF_16BE.name());
    charsets.add(StandardCharsets.UTF_16LE.name());
    charsets.add(StandardCharsets.ISO_8859_1.name());
    charsets.add(StandardCharsets.US_ASCII.name());
    charsets.add("UTF-32");
    charsets.add("GBK");
    charsets.add("GB2312");
    charsets.add("unicode");
    List<String> ss = Lists.newArrayList();
    ss.add("測");
    ss.add("a");
    ss.add("aa");
    ss.add("aaa");
    ss.add("\n");
    ss.add("\\");
    for (String s : ss){
        //字節測試
        System.out.println("---------"+"字符:\t"+s+"\t-------");
        for (String cs : charsets){
            System.out.println("在"+cs+"編碼下字節數爲:"+s.getBytes(cs).length);
        }
    }

}
執行結果
---------字符:	測	-------
在UTF-8編碼下字節數爲:3
在UTF-16編碼下字節數爲:4
在UTF-16BE編碼下字節數爲:2
在UTF-16LE編碼下字節數爲:2
在ISO-8859-1編碼下字節數爲:1
在US-ASCII編碼下字節數爲:1
在UTF-32編碼下字節數爲:4
在GBK編碼下字節數爲:2
在GB2312編碼下字節數爲:2
在unicode編碼下字節數爲:4
---------字符:	a	-------
在UTF-8編碼下字節數爲:1
在UTF-16編碼下字節數爲:4
在UTF-16BE編碼下字節數爲:2
在UTF-16LE編碼下字節數爲:2
在ISO-8859-1編碼下字節數爲:1
在US-ASCII編碼下字節數爲:1
在UTF-32編碼下字節數爲:4
在GBK編碼下字節數爲:1
在GB2312編碼下字節數爲:1
在unicode編碼下字節數爲:4
---------字符:	aa	-------
在UTF-8編碼下字節數爲:2
在UTF-16編碼下字節數爲:6
在UTF-16BE編碼下字節數爲:4
在UTF-16LE編碼下字節數爲:4
在ISO-8859-1編碼下字節數爲:2
在US-ASCII編碼下字節數爲:2
在UTF-32編碼下字節數爲:8
在GBK編碼下字節數爲:2
在GB2312編碼下字節數爲:2
在unicode編碼下字節數爲:6
---------字符:	aaa	-------
在UTF-8編碼下字節數爲:3
在UTF-16編碼下字節數爲:8
在UTF-16BE編碼下字節數爲:6
在UTF-16LE編碼下字節數爲:6
在ISO-8859-1編碼下字節數爲:3
在US-ASCII編碼下字節數爲:3
在UTF-32編碼下字節數爲:12
在GBK編碼下字節數爲:3
在GB2312編碼下字節數爲:3
在unicode編碼下字節數爲:8
---------字符:	
	-------
在UTF-8編碼下字節數爲:1
在UTF-16編碼下字節數爲:4
在UTF-16BE編碼下字節數爲:2
在UTF-16LE編碼下字節數爲:2
在ISO-8859-1編碼下字節數爲:1
在US-ASCII編碼下字節數爲:1
在UTF-32編碼下字節數爲:4
在GBK編碼下字節數爲:1
在GB2312編碼下字節數爲:1
在unicode編碼下字節數爲:4
---------字符:	\	-------
在UTF-8編碼下字節數爲:1
在UTF-16編碼下字節數爲:4
在UTF-16BE編碼下字節數爲:2
在UTF-16LE編碼下字節數爲:2
在ISO-8859-1編碼下字節數爲:1
在US-ASCII編碼下字節數爲:1
在UTF-32編碼下字節數爲:4
在GBK編碼下字節數爲:1
在GB2312編碼下字節數爲:1
在unicode編碼下字節數爲:4

最後爲簡單結論

'\n’是一個字符,佔1個字節 漢字若是用UTF-8編碼,佔3個字節,特別的漢字佔用4個字節 漢字若是用GBK編碼,佔2個字節。
漢字若是用UTF-16編碼,佔2個字節,特別的漢字佔用4個字節

字母若是用UTF-8編碼,佔1個字節。
字母若是用UTF-16編碼,佔2個字節。(至於下面代碼中,a佔4個,aa佔6個,aaa佔8個原因是,java在其中)
字母若是用UTF-32編碼,佔4個字節。 字母若是用GBK編碼,佔1個字節。 字母若是用GB2312編碼,佔1個字節。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章