去年的时候不记得是要做什么了,写了个用C#截取指定长度的方法,当时颇费了一番周折,因为想错了方向。
例如要截取字符串"我是1个中国人",取3位长度,那得到的结果是"我",如果取6位长度,得到的结果是"我是1",因为汉字是两个字节。
于是又重写了一发……
1 public static string GetSubString(string str, int length) 2 3 { 4 5 string temp = str; 6 7 int j = 0; 8 9 int k = 0; 10 11 for (int i = 0; i <temp.Length; i++) 12 13 { 14 15 if (Regex.IsMatch(temp.Substring(i, 1), @"[u4e00-u9fa5]+")) 16 17 { 18 19 j += 2; 20 21 } 22 23 else 24 25 { 26 27 j += 1; 28 29 } 30 31 if (j <= length) 32 33 { 34 35 k += 1; 36 37 } 38 39 if (j >= length) 40 41 { 42 43 return temp.Substring(0, k); 44 45 } 46 47 } 48 49 return temp; 50 51 } 52 53
具体思路是,定义两个变量:j 与K,例如要截取字符串"我是1个中国人",取3位长度,从第一个字符开始判断——temp.Substring(i, 1),如果是双字节j+2,否则加1,而变量K则每次循环加1,用来执行最后的截取操作。
当j <= 要截取的字节数,变量K停止加1。
当j >= 要截取的字节数,根据K返回截取后的结果。
看到别人的方法,都是最先将整个字符串中的中文替换成双字节,然后判断总长度是否大于需要截取的长度,如果大于再执行截取,而这样无疑是低效的(如果需要截取的字符串有1万个字符,需要返回的是20个字符,同时返回20条记录的话需要替换几十万次....),还要接下来再判断是该截取几位.....
1 public static string GetSubString(string str, int length) { 2 3 string temp = str; 4 5 int j = 0, k=0; 6 7 8 9 CharEnumeratorce = str.GetEnumerator(); 10 11 while (ce.MoveNext()) { 12 13 j += (ce.Current> 0 &&ce.Current< 255) ? 1 : 2 ; 14 15 16 17 if (j <= length) { 18 19 k++; 20 21 } else { 22 23 temp = str.Substring(0, k); 24 25 break; 26 27 } 28 29 } 30 31 32 33 return temp; 34 35 }
这个其实有问题,只能判断中文,应该判断所有双字节字符
1 public static string GetStrLenAll(string s, intlen, string style) 2 3 { 4 5 string temp = s; 6 7 if (Regex.Replace(temp, "[^x00-xff]", "zz", RegexOptions.IgnoreCase).Length <= len) 8 9 { 10 11 return temp; 12 13 } 14 15 for (int i = temp.Length; i >= 0; i--) 16 17 { 18 19 temp = temp.Substring(0, i); 20 21 if (Regex.Replace(temp, "[^x00-xff]", "zz", RegexOptions.IgnoreCase).Length <= len - style.Length) 22 23 { 24 25 return temp + style; 26 27 } 28 29 } 30 31 return ""; 32 33 }