過長的文本消息拆分-適用於微信消息推送
場景提出
故事要從微信消息推送說起,因爲微信對文本消息的推送限定字節數爲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個字節。