本文為原創(chuàng),如需轉(zhuǎn)載,請(qǐng)注明作者和出處,謝謝!
Web應(yīng)用程序在瀏覽器中顯示字符串時(shí),由于顯示長(zhǎng)度的限制,常常需要將字符串截取后再進(jìn)行顯示。但目前很多流行的語(yǔ)言,如C#、Java內(nèi)部采用的都是
Unicode
16(UCS2)編碼,在這種編碼中所有的字符都是兩個(gè)字符,因此,如果要截取的字符串是中、英文、數(shù)字混合的,就會(huì)產(chǎn)生問題,如下面的字符串:
String s = "a加b等于c,如果a等1、b等于2,那么c等3";
上面的字符串既有漢字,又有英文字符和數(shù)字。如果要截取前6個(gè)字節(jié)的字符,應(yīng)該是”a加b等",但如果用substring方法截取前6個(gè)字符就成了"a
加b等于c"。產(chǎn)生這個(gè)問題的原因是將substring方法將雙字節(jié)的漢字當(dāng)成一個(gè)字節(jié)的字符(UCS2字符)處理了。
要解決這個(gè)問題的方法是首先得到該字符串的UCS2編碼的字節(jié)數(shù)組,如下面的代碼如下:
byte[] bytes = s.getBytes("Unicode");
由于上面生成的字節(jié)數(shù)組中前兩個(gè)字節(jié)是標(biāo)志位,bytes[0] = -2,bytes[1] = -1,因此,要從第三個(gè)字節(jié)開始掃描,對(duì)于一個(gè)英文或數(shù)字字符,UCS2編碼的第二個(gè)字節(jié)是相應(yīng)的ASCII,第一個(gè)字節(jié)是0,如a的UCS2編碼是0 97,而漢字兩個(gè)字節(jié)都不為0,因此,可以利于UCS2編碼的這個(gè)規(guī)則來(lái)計(jì)算實(shí)際的字節(jié)數(shù),該方法的實(shí)現(xiàn)代碼如下:
public static String bSubstring(String s, int length) throws Exception
{
byte[] bytes = s.getBytes("Unicode");
int n = 0; // 表示當(dāng)前的字節(jié)數(shù)
int i = 2; // 要截取的字節(jié)數(shù),從第3個(gè)字節(jié)開始
for (; i < bytes.length && n < length; i++)
{
// 奇數(shù)位置,如3、5、7等,為UCS2編碼中兩個(gè)字節(jié)的第二個(gè)字節(jié)
if (i % 2 == 1)
{
n++; // 在UCS2第二個(gè)字節(jié)時(shí)n加1
}
else
{
// 當(dāng)UCS2編碼的第一個(gè)字節(jié)不等于0時(shí),該UCS2字符為漢字,一個(gè)漢字算兩個(gè)字節(jié)
if (bytes[i] != 0)
{
n++;
}
}
}
// 如果i為奇數(shù)時(shí),處理成偶數(shù)
if (i % 2 == 1)
{
// 該UCS2字符是漢字時(shí),去掉這個(gè)截一半的漢字
if (bytes[i - 1] != 0)
i = i - 1;
// 該UCS2字符是字母或數(shù)字,則保留該字符
else
i = i + 1;
}
return new String(bytes, 0, i, "Unicode");
}
下面代碼使用了bSubstring方法:
String s = "a加b等于c,如果a等1、b等于2,那么c等3";
System.out.println(bSubstring(s, 6));
上面的代碼截取的字符串是
"a加b等
"。
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining