C#和VB.net实现根据字节数截取字符串

本文介绍如何在C#中正确截取中英文及数字混合的字符串,避免因Unicode编码方式导致的问题,并提供了一个扩展方法实现按字节长度截取。
   Web应用程序在浏览器中显示字符串时,由于显示长度的限制,常常需要将字符串截取后再进行显示。但目前很多流行的语言,如C#、Java内部采用的都是Unicode 16(UCS2)编码,在这种编码中所有的字符都是两个字符,因此,如果要截取的字符串是中、英文、数字混合的,就会产生问题,如下面的字符串:
  1. String s = "a加b等于c,如果a等1、b等于2,那么c等3"

     上面的字符串既有汉字,又有英文字符和数字。如果要截取前6个字节的字符,应该是”a加b等",但如果用Substring方法截取前6个字符就成了"a加b等于c"。产生这个问题的原因是将Substring方法将双字节的汉字当成一个字节的字符(UCS2字符)处理了。 要解决这个问题的方法是首先得到该字符串的UCS2编码的字节数组,如下面的代码如下:

  1. byte[] bytes = System.Text.Encoding.Unicode.GetBytes(s);

    然后从第一个字节开始扫描,对于一个英文或数字字符,UCS2编码的第一个字节是相应的ASCII,第二个字节是0,如a的UCS2编码是97  0,而汉字两个字节都不为0,因此,可以利于UCS2编码的这个规则来计算实际的字节数,为了更方便,将按字节长度截取字符串的方法注册为String类的扩展方法,实现代码如下:

  1. public static class StringExt
  2. {
  3.     public static String bSubstring(this string s, int length)
  4.     {
  5.         byte[] bytes = System.Text.Encoding.Unicode.GetBytes(s);
  6.         int n = 0;  //  表示当前的字节数
  7.         int i = 0;  //  要截取的字节数
  8.         for (; i < bytes.GetLength(0) && n < length; i++)
  9.         {
  10.             //  偶数位置,如0、2、4等,为UCS2编码中两个字节的第一个字节
  11.             if (i % 2 == 0)
  12.             {
  13.                 n++;      //  在UCS2第一个字节时n加1
  14.             }
  15.             else
  16.             {
  17.                //  当UCS2编码的第二个字节大于0时,该UCS2字符为汉字,一个汉字算两个字节
  18.                 if (bytes[i] > 0)
  19.                 {
  20.                     n++;
  21.                 }
  22.             }
  23.         }
  24.         //  如果i为奇数时,处理成偶数
  25.         if (i % 2 == 1)
  26.         { 
  27.              //  该UCS2字符是汉字时,去掉这个截一半的汉字
  28.             if (bytes[i] > 0)
  29.                 i = i - 1;
  30.              //  该UCS2字符是字母或数字,则保留该字符
  31.             else
  32.                 i = i + 1;
  33.         }
  34.         return System.Text.Encoding.Unicode.GetString(bytes, 0, i);
  35.     }
  36. }

     在上面的代码中,如果最后要截取奇数个字符(以字节为单位),并且当最后一个字符是字母或数字,则保留该字符,如果是汉字,说明这个汉字被截了一半,则去掉这个汉字。

 

     可以使用下面的代码来截取字符串:

  1. String subStr = s.bSubstring(6);  //  substr的值是"a加b等"

 

补充,用VB.net实现:

  1. Public Module StringExt
  2.     Public Function bSubstring(ByVal s As StringByVal length As IntegerAs String
  3.         Dim bytes As Byte() = System.Text.Encoding.Unicode.GetBytes(s)
  4.         Dim n As Integer = 0
  5.         ' 表示当前的字节数 
  6.         Dim i As Integer = 0
  7.         ' 要截取的字节数 
  8.         While i < bytes.GetLength(0) AndAlso n < length
  9.             ' 偶数位置,如0、2、4等,为UCS2编码中两个字节的第一个字节 
  10.             If i Mod 2 = 0 Then
  11.                 n += 1
  12.                 ' 在UCS2第一个字节时n加1 
  13.             Else
  14.                 ' 当UCS2编码的第二个字节大于0时,该UCS2字符为汉字,一个汉字算两个字节 
  15.                 If bytes(i) > 0 Then
  16.                     n += 1
  17.                 End If
  18.             End If
  19.             i += 1
  20.         End While
  21.         ' 如果i为奇数时,处理成偶数 
  22.         If i Mod 2 = 1 Then
  23.             ' 该UCS2字符是汉字时,去掉这个截一半的汉字 
  24.             If bytes(i) > 0 Then
  25.                 i = i - 1
  26.             Else
  27.                 ' 该UCS2字符是字母或数字,则保留该字符 
  28.                 i = i + 1
  29.             End If
  30.         End If
  31.         Return System.Text.Encoding.Unicode.GetString(bytes, 0, i)
  32.     End Function
  33. End Module
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值