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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

public class Test10 {

    public static void main(String[] args) {
            
            //调用函数,输出测试
            System.out.println(mySubstring("HM程序员最强大",2));
            System.out.println(mySubstring("HM程序员最强大",4));
            System.out.println(mySubstring("HM程序员最强大",3));
            System.out.println(mySubstring("HM程序员最强大",10));
    }
   
    //定义一个方法,接收原始字符串和需要截取的字节数,返回截取到的字符串
    public static String mySubstring(String str,int count) {
            
            //定义一个byte[]
            byte[] bytes = null;
            //获取字节数组时,指定为按GBK编码获取,需要处理不支持GBK的机子上的异常
            try {
                    bytes = str.getBytes("GBK");
            } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }
            //判断输入的字节个数是不是正整数
            if(count<0)
                    throw new RuntimeException("获取字节个数为负数,错误!");
            //判断输入的字节个数是否大于原始字符串长度,是,则输出原字符串
            else if(count>str.length())
                    return str;
            //判断输入的字节个数是不是奇数
            else if(count>0 && count%2==1) {
                    //是奇数,才判断要获取的最后一个字节是不是汉字的一半,通过负数判断
                    if((byte)bytes[count-1]<0){
                            //是汉字一半,就减一个字节
                            count--;
                    }
            }
            
            //获取要得到的新字节数组
            byte[] newbytes=new byte[count];
            for(int x=0;x<count;x++){
                    newbytes[x]=bytes[x];
            }
            
            //将新字节数组转回字符串,并返回
            String newStr=new String(newbytes);
            return newStr;
    }

}

14 个回复

正序浏览
// 导入java.util下的所有类
import java.io.*;
/**
* Description:
* <br>Webside: <a >GitHub Of ZallerTing</a>
* <br>Date: 2016-12-21
* @author Zaller.Ting zallerting@gmail.com
* @version 1.0
* 微信/Wechat: ZALLER-TING
* QQ: 851509660
* Location:Kunshan
* 实现输入(待截取字串,开始截取字节索引,截取字节长度)后,输出截取字节长度子串,不出现半个中文字符(?)
*/
public class CutStringByByte {
        // 表示开始截取字节索引,首字符索引,字串最大长度,字串最大字节长度,子串长度,子串字节长度,前部分截取字节长度,截取字节长度,半个中文字符数量,临时变量
        protected static int startByteIndex, firstStrIndex, maxStrLen, maxByteLen, subLen, subByteLen, beforeCutByteLen, cutByteLen, halfHanNum, tmp;
        // 表示键盘输入的一行数据,待截取字串,截取子串变量
        protected static String inputStr, beCutStr, subStr;
        // 表示键盘输入的单个字符变量
        protected static char ch;
        // 表示键盘输入的一行数据组成的数组
        protected static String[] inputStrArr;
        // 表示以GBK编码方式解析的字节数组
        protected static byte bytesByGBK[];
        // 判断截取字节索引及截取字节长度是否在有效范围
        protected static boolean isProperIndex, isProperLen;
       
        // 判断是否为数值型字符串的方法(正数)
        protected static boolean isNumbericStr(String inputStr) {
                for(int i = 0; i < inputStr.length(); i++) {
                        // 返回指定索引处的字符
                        ch = inputStr.charAt(i);
                        if(ch < 46 || ch > 57) {
                                return false;
                        }
                }               
                return true;
        }
       
        // 判断是否为数值型字符串的方法(负数)
        protected static boolean isNegativeStr(String inputStr) {
                ch = inputStr.charAt(0);
                if(ch == '-') {
                        return true;
                }       
                return false;
        }
       
        // 统计半个中文字符的数量
        protected static int halfHanNum(int startByteIndex) {
                // 初始化halfHanNum变量
                halfHanNum = 0;
                for(int i = 0; i <= startByteIndex; i++) {
                        // 字节索引对应值小于0时halfHanNum加1
                        if(bytesByGBK < 0) {
                                ++halfHanNum;
                        }
                }
                return halfHanNum;
        }
       
        // 找出需要截取子串第1个字符索引
        protected static int find1stStrIndex(int startByteIndex, String subStr) {
                // 统计半个中文字符的数量
                halfHanNum(startByteIndex);
                // startByteIndex字节索引对应字符为非中文单字节字符, 取subStr最后1个字符
                if(bytesByGBK[startByteIndex] > 0) {
                        firstStrIndex = subStr.length() > 0 ? subStr.length() - 1 : 0;
                // startByteIndex字节索引为中文字符第1个字节, 取subStr后面1个字符
                } else if(halfHanNum % 2 == 1){
                        firstStrIndex = subStr.length();
                // startByteIndex字节索引为中文字符第2个字节, 取subStr后面1个字符
                } else if(halfHanNum % 2 == 0){
                        firstStrIndex = subStr.length();
                }
                return firstStrIndex;
        }

        // 从指定字节索引startByteIndex截取cutByteLen长度的子串方法
    public static void subStr(String beCutStr, int startByteIndex, int cutByteLen) throws IOException  {
                /**
                 * 分两部分计算:
                 * 一.截取从索引startByteIndex开始的maxStrLen长度的子串:
                 *   1.截取从索引0开始的startByteIndex+1长度的子串;
                 *   2.找出需要截取子串的第1个字符索引firstStrIndex;
                 *   3.截取从索引firstStrIndex开始的maxStrLen长度的子串;
                 *   
                 * 二.截取从索引startByteIndex开始的cutByteLen长度的子串:
                 *   1.重新计算需要截取字串最大长度maxStrLen;
                 *   2.截取从索引firstStrIndex开始的cutByteLen长度的子串;
                 *   3.返回从startByteIndex字节索引截取cutByteLen长度的子串subStr;
                 */
                         
                /**
                 * 第一部分:截取从索引startByteIndex开始的maxStrLen长度的子串
                 */
                // 字串最大长度
                maxStrLen = beCutStr.length();
                // 字串最大字节长度
                maxByteLen = beCutStr.getBytes().length;
                // 前一部分截取字节长度
                beforeCutByteLen = startByteIndex > 0 ? startByteIndex + 1 : 0;
                // 从索引[0]截取长度[beforeCutByteLen]的子串
                subStr = beCutStr.substring(0, beforeCutByteLen > maxStrLen ? maxStrLen : beforeCutByteLen);
                // 子串字节长度
                subByteLen = subStr.getBytes("GBK").length;
                // 子串字节长度赋给临时变量tmp
                tmp = subByteLen;
                // 前部分截取字节长度小于子串字节长度时
                while(beforeCutByteLen < subByteLen) {
                        // 临时变量减1
                        --tmp;
                        subStr = beCutStr.substring(0, tmp > maxStrLen ? maxStrLen : tmp);
                        subByteLen = subStr.getBytes("GBK").length;
                }
                // 找出需要截取子串第1个字符索引
                find1stStrIndex(startByteIndex, subStr);
                // 找出需要截取子串
                subStr = beCutStr.substring(firstStrIndex, maxStrLen);
                /**
                 * 第二部分:截取从索引startByteIndex开始的cutByteLen长度的子串
                 */
                // 子串字节长度
                subByteLen = subStr.getBytes("GBK").length;
                // 重新计算需要截取字串最大长度
                maxStrLen = maxStrLen - firstStrIndex;
                // 子串字节长度赋给临时变量tmp
                tmp = subByteLen;
                // 需要截取字节长度小于子串字节长度时
                while(cutByteLen < subByteLen) {
                        // 需要截取字节长度减1
                        --tmp;
                        subStr = subStr.substring(0, tmp > maxStrLen ? maxStrLen : tmp);
                        subByteLen = subStr.getBytes("GBK").length;
                }                       
                System.out.println("“" + beCutStr + "” 从第" + startByteIndex + "字节索引截取" + cutByteLen + "字节的子串为: " + subStr + "\n");               
        }       
       
        // 主方法,程序的入口
        public static void main(String[] args) throws IOException {
                System.out.println("【本软件实现从指定字节索引截取指定字节长度子串的功能】\n");
                System.out.print(" 以【待截字串,开始截取字节索引,截取字节长度】格式输入 :");
                // 获取键盘输入字符串
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                while((inputStr = br.readLine()) != null) {
                        // 通过英文逗号分隔键盘输入的字符串
                        inputStrArr = inputStr.split(",");
                    // 将键盘输入的第1个参数以"GBK"编码形式译码成1个字节数组
                    bytesByGBK = inputStrArr[0].getBytes("GBK");
                        // 判断是否键盘输入包含英文逗号且以逗号分隔的字符串中第1个不为null
                        if(inputStr.contains(",") && !inputStr.contains(",") && inputStrArr[0] != null) {
                                // 判断是否键盘输入第2个及第3个均为数值型字符串
                                if(isNumbericStr(inputStrArr[1]) && isNumbericStr(inputStrArr[2])) {
                                        // 转换数值型字符串为对应数值
                                        startByteIndex = Integer.parseInt(inputStrArr[1]);
                                        cutByteLen = Integer.parseInt(inputStrArr[2]);
                                        // 判断键盘输入的第2个及第3个数值是否在合理范围内
                                        isProperIndex = startByteIndex >= 0 && startByteIndex <= bytesByGBK.length ? true : false;
                                        isProperLen = cutByteLen >= 0 && cutByteLen <= bytesByGBK.length - startByteIndex ? true : false;       
                                        // 再判断截取字串字节索引及字节长度是否正确
                                        if(isProperIndex) {
                                                if(isProperLen) {
                                                        // 从指定索引位置截取指定字节长度的子串
                                                        subStr(inputStrArr[0], startByteIndex, cutByteLen);
                                                } else {
                                                        System.out.println("截取字节长度输入有误!");
                                                }
                                        } else {
                                                System.out.println("开始截取字节索引输入有误!");
                                        }
                                // 判断是否键盘输入第2个及第3个均为负数值型字符串
                                } else if(isNegativeStr(inputStrArr[1]) && isNegativeStr(inputStrArr[2])){
                                        System.out.println("开始截取字节索引及截取字节长度均输入有误!");
                                } else if(isNegativeStr(inputStrArr[1]) && !isNegativeStr(inputStrArr[2])){
                                        System.out.println("开始截取字节索引输入有误!");
                                } else if(!isNegativeStr(inputStrArr[1]) && isNegativeStr(inputStrArr[2])){
                                        System.out.println("截取字节长度输入有误!");
                                }
                        // 判断是否键盘输入包含中文逗号
                        } else if(inputStr.contains(",")) {
                                System.out.println("请以英文逗号分隔字串、字节索引、字节长度!");
                        } else {
                                System.out.println("待截取字串输入为空!");
                        }
                        System.out.print(" 以【待截字串,开始截取字节索引,截取字节长度】格式输入 :");
                }
        }
}
回复 使用道具 举报
学习了,哈
回复 使用道具 举报
public class Test10 {
        public static void main(String[] args) throws UnsupportedEncodingException {
                System.out.println("请输入一个字符串");
                String s =new Scanner(System.in).nextLine();
                System.out.println("请输入要截取的长度");
                int n =new Scanner(System.in).nextInt();
                cut(s,n);
               
        }

        private static void cut(String s, int n) throws UnsupportedEncodingException {
                byte[] b = s.getBytes("gbk");
                //定义cout1接收数组正数出现的次数
                //定义cout2接受数组负数出现的次数
                int cout1 = 0;
                int cout2 =0;
                for(int i = 0;i<=n-1;i++){
                        if(b[i]>0){
                                cout1+=1;
                        }else{
                                cout2+=1;
                        }
                }
                //正数出现说明是字符计入需截取长度中,负数出现一次则不计入,出现两次,说明是一个汉字,截取长度+1
                int sum = cout1+ (int)(cout2/2);
                String s3=s.substring(0, sum);
                System.out.println(s3);
        }
}
回复 使用道具 举报
好多大神...
回复 使用道具 举报
xiao_D 高级黑马 2015-10-23 05:42:34
11#
lclxjzz 发表于 2015-4-11 15:24
学习了  楼主的对的

我就呵呵了  感谢楼主抛砖引玉
回复 使用道具 举报
xiao_D 高级黑马 2015-10-23 05:40:21
10#

计数器这个点子好,  往前遍历    这个不错哦
回复 使用道具 举报
xiao_D 高级黑马 2015-10-23 05:37:54
9#
好low的代码啊
回复 使用道具 举报
        我学过都忘了. .
回复 使用道具 举报
愚翁 中级黑马 2015-6-17 17:09:01
7#
写得很清楚,谢谢!
回复 使用道具 举报
请输入一个字符串写
h中h国h好

请输入要截取的字符的个数
2
h?

请输入要截取的字符的个数
3
h?
回复 使用道具 举报
代码不对呀!出问题了
回复 使用道具 举报
学习了  楼主的对的
回复 使用道具 举报
楼主的应该不对吧
回复 使用道具 举报
  1. package com.itheima;

  2. import java.io.IOException;
  3. import java.util.Scanner;

  4. /**
  5. 需求:编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表)。
  6.                 例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,截取3个字节也要是"HM"而不要出现半个中文

  7. 思路:  输入一个字符串,和要截取的字数
  8.                 定义一个函数,函数功能:从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表)
  9.                 把字符串转成字节数组
  10.                 因为中文GBK是返回两个负数,所以从最后一个开始往前遍历
  11.                 定义一个计数器,遍历,如果便利到负数就+1。
  12.                 如果负数个数为单数,那么为半个中文,舍弃,返回-1之前的数,转换成字符串输出
  13.                 否则为一个中文,转换成字符串输出
  14.                 @author run_wind
  15. */

  16. class Test10
  17. {               
  18.         public static void main(String[] args) throws IOException
  19.         {
  20.         
  21.                 Scanner in = new Scanner(System.in);//获取键盘输入的实例
  22.                 System.out.print("请输入字符串(直接回车默认HM程序员):");
  23.                 String string = in.nextLine();
  24.                 if (string.equals(""))
  25.                                 string = "HM程序员";
  26.                 System.out.print("请输入截取的字节数:");
  27.                 int byte_num = in.nextInt();
  28.                
  29.         Test10 t10 = new Test10();
  30.         System.out.println(t10.getString(string, byte_num));
  31.      }
  32.        
  33.         //函数功能:从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表)
  34.         public String getString(String str,int key) throws IOException
  35.         {       
  36.                 byte[] buf = str.getBytes("gbk");//编码
  37.                
  38.                 //因为中文GBK是返回两个负数,所以从最后一个开始往前遍历
  39.                 //如果负数个数为单数,那么为半个中文,舍弃,否则为一个中文,返回
  40.                 int count = 0;
  41.                 for(int x=key-1; x>=0; x--)
  42.                 {
  43.                         if(buf[x]<0)
  44.                                 count++;
  45.                         else
  46.                                 break;
  47.                 }
  48.                
  49.                 if(count%2==0)//解码。如果为单数就是半个中文,要舍弃最后的数
  50.                         return new String(buf,0,key,"gbk");
  51.                 else
  52.                         return new String(buf,0,key-1,"gbk");
  53.         }
  54. }
复制代码
回复 使用道具 举报 1 0
您需要登录后才可以回帖 登录 | 加入黑马