编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表),两种方法的比较。

黑马基础测试的最后一道题,写代码时费了点儿劲,发现挺有意思的,结合大牛们的宝贵经验,总结了两种方法,端上来与大家分享,热乎的~~~

题目:从“HM程序员训练营”中截取2个字节是“HM”,截取4个则是“HM程”,截取3个字节也要是"HM"而不要出现半个中文。

分析:题目的要求是从字符串中按字节数截取,所以字符串转换为字节数组是肯定的,字母还好说,就占一个字节,问题的关键在于字符串中有汉字的出现,GBK编码中汉字字符是占两个字节的,两个字节分开无法识别,当截取的字节数最后一位是代表半个字符的字节时,运行结果中的字符串末尾会出现“?”以表示最后一个字节无法识别。所以需要在程序中将这种情况回避掉,只显示整个的汉字字符。

第一种方法:通过比较新子串和源字符串相同位置上的字符是否相等来判断新子串中最后一个字节是否可以识别,如果相同则说明最后截取的是一个完整的汉字,如果不同则说明新子串的字节数组最后一个字节是一个汉字的半边,需要舍弃,所以数组指针向左移一位,以保证完整的汉字输出。此方法条理清楚,可阅读性较强。

public static void byteSubStr(String str , int len)
{
String s = null; //初始化字符串s,赋值为空
if(str != null) //传入的字符串不能为空
{
byte[] a = null; //初始化字节数组,赋值为空
try 
{
a = str.getBytes("GBK"); //将字符串转化为字节数组,GBK码表,此时字节数组的长度为14

catch (UnsupportedEncodingException e) //捕捉编码失败异常
{
e.printStackTrace();
}
//System.out.println("String length:"+a.length);打印字节数组的长度
if(a.length <= len)
{
s = str; //如果要求取出的字节长度大于字节数组应有长度,则将s初始化为str
}
else if(len > 0)
{
s = new String(a, 0, len); //如果字节长度在字节数组长度范围内,则根据要求取出长度len,创建新的字符串s。
int length = s.length(); //获取新字符串的长度
//System.out.println(s.length());
if(str.charAt(length - 1) != s.charAt(length-1))//如果原字符串中相应位置上的字符与
//字符串相应位置上的字符不相等,说明新字符串中相应位置只有半个中文,则应该讲数组指针向左移一位,形成新的子串。
{
if(length < 2)
{
s = null; //如果新字符串的长度小于2,则将新字符串赋值为空。
}

else
{
s = s.substring(0, length - 1); //将符合条件的子串复制给s
}
}
}
}
System.out.println(s);
}


第二种方法:相比较而言,个人觉得第二种方法比较不容易看懂,需要费点儿功夫,首先,在字符串判断的使用使用的是三目运算符,看上去很赞,

接下来在判断新子串是否符合要求时使用了while方法,通过不断的循环比较,数组指针向左移动来获取到最后的字符子串。

public static voidbyteSubStr(String str, int length)
{   
            if (str == null)    
            System.out.println("String is null...");    
            else
           {   
            int len = length; //获取要截取的字节数  
            //System.out.println("len:"+len);
            //System.out.println("strlength:"+str.length());//8

            String s = str.substring(0, str.length() < length ? str.length() : length);  
            //判断如果要截取的字节数长度大于原字符串本身的长度,则仍以原字符串为准,否则获取新子串。规则为包含头不包含尾。
            //System.out.println("s1:"+s);
            int byteLens = 0; //初始化字节数组长度
try 
{
byteLens = s.getBytes("GBK").length; //按照GBK码表将原字符串或子串转为字节数组,并获取字节数组长度。
//System.out.println("byteLens:"+byteLens);


catch (UnsupportedEncodingException e) //捕获编码异常
{
e.printStackTrace();
}      
             while (byteLens > len) //如果字节数组长度大于要截取的字节数,说明有汉语字符的存在
            {    
                int subLength = --length;  
                //System.out.println("subLength:"+subLength);
                s = str.substring(0, subLength > str.length() ? str.length() : subLength); 
                //判断新子串长度和原子串长度,true返回原子串长度,false返回新子串长度
                //System.out.println("s2:"+s);
                try
                {
byteLens = s.getBytes("GBK").length;
//System.out.println("byteLens:"+byteLens);
}
                catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}   
            }    
            System.out.println("String:"+s);   
        }  
 }  



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值