A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Alexander 中级黑马   /  2014-3-4 11:51  /  967 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

问题:从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表)
例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,截取3个字节也要是"HM"而不要出现半个中文
这题,刚才是想用String的subString()方法来获取,但比较麻烦的是遇到汉字就不好用了,汉字是两个字节,字母是一个字节
怎么判断最后的字节是否占汉字的一半呢?请高手解答,并说出判断的方法是什么?

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

5 个回复

倒序浏览
class SplitString  {
  private String str;
  private   int byteNum;
  public SplitString() {}
  public SplitString(String str, int byteNum)
  {
  this .str = str;
  this .byteNum = byteNum;
回复 使用道具 举报
分析:题目的要求是从字符串中按字节数截取,所以字符串转换为字节数组是肯定的,字母还好说,就占一个字节,问题的关键在于字符串中有汉字的出现,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技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
Dora 发表于 2014-3-4 13:46
分析:题目的要求是从字符串中按字节数截取,所以字符串转换为字节数组是肯定的,字母还好说,就占一个字节 ...

创建新字符串 然后判断是否包含 如真则直接返回 假则返回其子串就好了
回复 使用道具 举报
本帖最后由 老貓钓鱼 于 2014-3-4 14:21 编辑

public class TestDemo {

        public static void main(String[] args) throws IOException {
                String str = "HM程序员";
                byte[] by = str.getBytes();
                int val = 3; //由你指定的字节数
                for (int i = 0; i < val; i++) {
                        if(by < 0) {    //如果小于0,证明这个字是汉字
                                if((i+1)>=val || (i+1) >= by.length) { //因为是汉字所以需要读取现字节和下一个字节,因此判断会不会越界(数组越界或你指定的字节)   
                                        System.out.println("最后一个汉字只占汉字的一半");
                                }else{  //没有越界的情况下读出2个字节所对应的汉字
                                        byte[] by1 = {by, by[i+1]};
                                        System.out.println(new String(by1));
                                        i++;
                                }
                        }else{//不是汉字的直接读出来
                                System.out.println((char)by);
                        }
                }
        }
}


1.jpg (128.73 KB, 下载次数: 5)

1.jpg

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
ixiangfeng 发表于 2014-3-4 13:53
创建新字符串 然后判断是否包含 如真则直接返回 假则返回其子串就好了

这个想法不错,试试看!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马