C#、Java實現按字節截取字符串包含中文漢字和英文字符數字標點符號等


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”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM