C#、Java實現按字節截取字符串,字符串中包含中文漢字和英文字符數字標點符號等。
在實際項目應用過程中,尤其是在web開發時可能遇到的比較多,就以我的(JiYF笨小孩管理系統)為例,再發布文章時候,文章摘要如果用戶沒有填寫,默認截取文章前面255個字節,這個時候里面難免包含中文漢字,英文字母,標點符號等等有可能就會遇到截取出半個漢字的情況。
以Unicode 16(UCS2)編碼為例,每一個字符占用倆個字節
假如字符串s:
String s = "潮哥shuo丑安ni去哪?";
上面的s字符串既有漢字,又有英文字符和數字
舉例:
如果要截取前6個字節的字符,應該是”潮哥sh",但如果用substring方法截取前6個字符就成了"潮哥shuo"。
如果截取9個字節,應該是“潮哥shuo” 丑的半個漢字就去掉了,但如果用substring方法截取前9個字符就成了"潮哥shuo丑安n"。
產生這個問題的原因是將substring方法將雙字節的漢字當成一個字節的字符(UCS2字符)處理了。 要解決這個問題的方法是首先得到該字符串的UCS2編碼的字節數組,如下面的代碼如下:
C#代碼示例:
1 private static string cutSubstring(string str, int length) 2 { 3 if (str == null || str.Length == 0 || length < 0) 4 { 5 return ""; 6 } 7 8 byte[] bytes = System.Text.Encoding.Unicode.GetBytes(str); 9 int n = 0; // 表示當前的字節數 10 int i = 0; // 要截取的字節數 11 for (; i < bytes.GetLength(0) && n < length; i++) 12 { 13 // 偶數位置,如0、2、4等,為UCS2編碼中兩個字節的第一個字節 14 if (i % 2 == 0) 15 { 16 n++; // 在UCS2第一個字節時n加1 17 } 18 else 19 { 20 // 當UCS2編碼的第二個字節大於0時,該UCS2字符為漢字,一個漢字算兩個字節 21 if (bytes[i] > 0) 22 { 23 n++; 24 } 25 } 26 } 27 // 如果i為奇數時,處理成偶數 28 if (i % 2 == 1) 29 { 30 // 該UCS2字符是漢字時,去掉這個截一半的漢字 31 if (bytes[i] > 0) 32 i = i - 1; 33 // 該UCS2字符是字母或數字,則保留該字符 34 else 35 i = i + 1; 36 } 37 return System.Text.Encoding.Unicode.GetString(bytes, 0, i); 38 }
分析:

測試結果:
調用
cutSubstring("潮哥shuo丑安ni去哪?",6);------>運行結果:“潮哥sh”
cutSubstring("潮哥shuo丑安ni去哪?",9);------>運行結果:“潮哥shuo”
Java代碼示例:
(細心的童鞋會發現i值不同,java是從2開始C#從0開始,這里注意,java轉換為字節數組,前倆個字節是標志位,所以第0位和第1位是標志位,從2開始)
1 public static String bSubstring(String s, int length) throws Exception 2 { 3 4 byte[] bytes = s.getBytes("Unicode"); 5 int n = 0; // 表示當前的字節數 6 int i = 2; // 要截取的字節數,從第3個字節開始 7 for (; i < bytes.length && n < length; i++) 8 { 9 // 奇數位置,如3、5、7等,為UCS2編碼中兩個字節的第二個字節 10 if (i % 2 == 1) 11 { 12 n++; // 在UCS2第二個字節時n加1 13 } 14 else 15 { 16 // 當UCS2編碼的第一個字節不等於0時,該UCS2字符為漢字,一個漢字算兩個字節 17 if (bytes[i] != 0) 18 { 19 n++; 20 } 21 } 22 } 23 // 如果i為奇數時,處理成偶數 24 if (i % 2 == 1) 25 26 { 27 // 該UCS2字符是漢字時,去掉這個截一半的漢字 28 if (bytes[i - 1] != 0) 29 i = i - 1; 30 // 該UCS2字符是字母或數字,則保留該字符 31 else 32 i = i + 1; 33 } 34 35 return new String(bytes, 0, i, "Unicode"); 36 }
測試結果:
調用
cutSubstring("潮哥shuo丑安ni去哪?",6);------>運行結果:“潮哥sh”
cutSubstring("潮哥shuo丑安ni去哪?",9);------>運行結果:“潮哥shuo”
