2025-02-09

編寫一個截取字符串的函數,輸入為一個字符串和字節數,輸出為按字節截取的字符串。但是要保證漢字不被截半個,如”我ABC”4,應該截為”我AB”,輸入”我ABC漢DEF”,6,應該輸出為”我ABC”而不是”我ABC+漢的半個”。


  public static String substring(String str, int toCount,String more)


  {


  int reInt = 0;


  String reStr = “”;


  if (str == null)


  return “”;


  char[] tempChar = str.toCharArray();


  for (int kk = 0; (kk < tempChar.length && toCount > reInt); kk++) {


  String s1 = str.valueOf(tempChar[kk]);


  byte[] b = s1.getBytes();


  reInt += b.length;


  reStr += tempChar[kk];


  }


  if (toCount == reInt || (toCount == reInt – 1))


  reStr += more;


  return reStr;


  }


  Web應用程序在瀏覽器中顯示字符串時,由於顯示長度的限制,常常需要將字符串截取後再進行顯示。但目前很多流行的語言,如C#、Java內部采用的都是 Unicode 16(UCS2)編碼,在這種編碼中所有的字符都是兩個字符,因此,如果要截取的字符串是中、英文、數字混合的,就會產生問題,如下面的字符串:


  String s = “a加b等於c,如果a等1、b等於2,那麼c等3”;


  上面的字符串既有漢字,又有英文字符和數字。如果要截取前6個字節的字符,應該是”a加b等”,但如果用substring方法截取前6個字符就成瞭”a 加b等於c”。產生這個問題的原因是將substring方法將雙字節的漢字當成一個字節的字符(UCS2字符)處理瞭。要解決這個問題的方法是首先得到該字符串的UCS2編碼的字節數組,如下面的代碼如下:


  byte[] bytes = s.getBytes(“Unicode”);


  由於上面生成的字節數組中前兩個字節是標志位,bytes[0] = -2,bytes[1] = -1,因此,要從第三個字節開始掃描,對於一個英文或數字字符,UCS2編碼的第二個字節是相應的ASCII,第一個字節是0,如a的UCS2編碼是0  97,而漢字兩個字節都不為0,因此,可以利於UCS2編碼的這個規則來計算實際的字節數,該方法的實現代碼如下:


  public static String bSubstring(String s, int length) throws Exception


  {


  byte[] bytes = s.getBytes(“Unicode”);


  int n = 0; // 表示當前的字節數


  int i = 2; // 要截取的字節數,從第3個字節開始


  for (; i < bytes.length && n < length; i++)


  {


  // 奇數位置,如3、5、7等,為UCS2編碼中兩個字節的第二個字節


  if (i % 2 == 1)


  {


  n++; // 在UCS2第二個字節時n加1


  }


  else


  {


  // 當UCS2編碼的第一個字節不等於0時,該UCS2字符為漢字,一個漢字算兩個字節


  if (bytes[i] != 0)


  {


  n++;


  }


  }


  }


  // 如果i為奇數時,處理成偶數


  if (i % 2 == 1)


  {


  // 該UCS2字符是漢字時,去掉這個截一半的漢字


  if (bytes[i – 1] != 0)


  i = i – 1;


  // 該UCS2字符是字母或數字,則保留該字符


  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等”。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *