編寫一個(gè)截取字符串的函數(shù),輸入為一個(gè)字符串和字節(jié)數(shù),輸出為按字節(jié)截取的字符串。 但是要保證漢字不被截半個(gè),如"我ABC"4,應(yīng)該截為"我AB",輸入"我ABC漢DEF",6, 應(yīng)該輸出為"我ABC"而不是"我ABC+漢的半個(gè)"。 import java.io.UnsupportedEncodingException; /** * 截取的要點(diǎn): * 1.首先將字符串轉(zhuǎn)換成字節(jié)數(shù)組,再將字節(jié)數(shù)組的每個(gè)元素拿出來,判斷有無負(fù)數(shù)(一個(gè)漢字為兩個(gè)負(fù)數(shù)),即有漢字 * 2.len:這個(gè)len是將字符串轉(zhuǎn)換成字節(jié)數(shù)組的要截取的長度, * 如"我ABC你"的字節(jié)數(shù)組長度為7(-50,-46,65,66,67,-60,-29),而截取的是6(-50,-46,65,66,67,-60), * 3.對截取的字節(jié)數(shù)組(-50,-46,65,66,67,-60)統(tǒng)計(jì)負(fù)數(shù)的個(gè)數(shù) * 4.String里的方法substring方法將雙字節(jié)的漢字當(dāng)成一個(gè)字節(jié)的字符(UCS2字符)處理了,而我們的字節(jié)數(shù)組一個(gè)函數(shù) * 就是兩個(gè)字節(jié),所以要想用substring方法,還需要將負(fù)數(shù)的個(gè)數(shù)count除以二才可以 * @author Administrator * */ public class TestJq { public static String subString(String str, int len) { if (str == null && "".equals(str)) { return null; } // 將字符串中的char數(shù)組轉(zhuǎn)換成指定編碼方式的byte數(shù)組的函數(shù) byte[] strBytes = null; try { strBytes = str.getBytes("GBK"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 得到字符串的長度,判斷截取字符串的長度是否在判斷的范圍內(nèi),否則返回原串 int strLen = strBytes.length; if (len >= strLen || len < 1) { return str; } System.out.println("strBytes.length="+strBytes.length); System.out.println("len="+len); int count = 0; for (int i = 0; i < len; i++) { // 將每個(gè)字節(jié)數(shù)組轉(zhuǎn)換為整型數(shù),以為后面根據(jù)值的正負(fù)來判斷是否為漢字 int value = strBytes[i]; System.out.print(value+","); //我ABC你 -50,-46,65,66,67,-60,-29 //對于第一種情況: //注,一個(gè)函數(shù)轉(zhuǎn)換成整型數(shù)就為兩個(gè)負(fù)整數(shù),上面的”我ABC你“, //轉(zhuǎn)換成整型數(shù)就為-50,-46,65,66,67,-60,-29,但是len=6,所以截取下來的就是-50,-46,65,66,67,-60,count就為3 // 如果是漢字(負(fù)),則統(tǒng)計(jì)截取字符串中的漢字所占字節(jié)數(shù) if (value < 0) { count++; } System.out.println("zh count="+count); } // 依據(jù)判斷給定的字符串是否含有漢字,利用String類的substring()方法來截取不同的長度 // 根據(jù)所統(tǒng)計(jì)的字節(jié)數(shù),判斷截取到字符是否為半個(gè)漢字,奇數(shù)為半個(gè)漢字 if (count % 2 != 0) { // 如果在截取長度為1時(shí),則將該漢字取出, // 其他情況則不截取這里的截取長度則按字符長度截?。ń厝∽止?jié)長度數(shù)-截取漢字字節(jié)數(shù)/2-截取到的半個(gè)漢字的字節(jié)數(shù)) len = (len == 1) ? len : len - count / 2 - 1; //len=6-3/2-1=4 我ABC // System.out.println("處理后的len="+len); } else { // 截取字符長度為字節(jié)長度-漢字所占字節(jié)長度/2(漢字占兩個(gè)字節(jié)) len = len - (count / 2); } return str.substring(0, len); } public static void main(String[] args) { // String inStrTest = "我ABC你EFG"; // String strTest = inStrTest.substring(0, 2); // System.out.println(strTest); System.out.println("--------- 情況一-----------"); // 情況一: String inStr = "我ABC你"; String str = subString(inStr, 6); System.out.println(str); // 我ABC www. System.out.println("---------- 情況二----------"); // 情況二:首字符為漢字 inStr = "我ABC漢DEF"; str = subString(inStr, 1); System.out.println(str); // 我 System.out.println("-----------情況三---------"); // 情況三:中間有連續(xù)漢字 inStr = "我AB愛孩子CDEF"; str = subString(inStr, 9); System.out.println(str); // 我AB愛孩 System.out.println("-----------情況四---------"); // 情況四:沒有漢字 inStr = "ABCDEF"; str = subString(inStr, 4); System.out.println(str); // ABCD } } Web應(yīng)用程序在瀏覽器中顯示字符串時(shí),由于顯示長度的限制,常常需要將字符串截取后再進(jìn)行顯示。但目前很多流行的語言,如C#、Java內(nèi)部采用的都是Unicode 16(UCS2)編碼,在這種編碼中所有的字符都是兩個(gè)字符,因此,如果要截取的字符串是中、英文、數(shù)字混合的,就會產(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é)開始掃描,對于一個(gè)英文或數(shù)字字符,UCS2編碼的第二個(gè)字節(jié)是相應(yīng)的ASCII,第一個(gè)字節(jié)是0,如a的UCS2編碼是0 97,而漢字兩個(gè)字節(jié)都不為0,因此,可以利于UCS2編碼的這個(gè)規(guī)則來計(jì)算實(shí)際的字節(jié)數(shù) |
|