面试题之——对包含汉字的字符串截取指定字节数

时间:2023-01-12 16:03:28

题目:编写一个截取字符串的函数,输入为一个字符串和字节数, 输出为按字节截取的字符串,但要保证汉字不被截取半个,如"我ABC",4,应该截取"我AB",输入"我ABC汉DEF",6, 应该输出"我ABC",而不是"我ABC+汉的半个"。

我们都知道在计算机中,存储一个汉字需要至少两个字节。例如:gbk和gb2312都是用两个字节存储一个汉字,而UTF-8是用三个字节存储一个汉字。关于字符编码请看:汉字与字符编码。下面使用两种方法对字符串进行截取。

第一种方法

适用字符集:UTF-8,gb2312,gbk

思路:依次截取字符串的每个字符,根据字符编码获取其字节数temp_len,total用以记录每次截取字符后及之前截取字符字节数之和,然后判断total是否小于等于所需要截取字节长度(length),如果小于说明还没超过所需要截取字节长度,那么截取字符的长度(len)+1,如果total>length说明已经超出所需要截取的字节长度,此时的len就是所需要截取原字符串的长度

第二种方法

适用字符集:gb2312,gbk

gbk汉字编码是两个字节为一个字符,高字节是小于0的(原因我也不清楚),设置一标志变量bChineseFirstHalf为false,如果获取到的字节小于0且bChineseFirstHalf为false,说明这是汉字的前半个字节,则bChineseFirstHalf设置为true,否则,num(最终需要截取字符串长度)加1。一直循环到字节数i等于需要截取的字节数length

具体代码

package com.zyh.interview;

import java.io.UnsupportedEncodingException;

/**
 * 编写一个截取字符串的函数,输入为一个字符串和字节数, 输出为按字节截取的字符串,但要保证汉字不被截取半个,
 * 如"我ABC",4,应该截取"我AB",输入"我ABC汉DEF",6, 应该输出"我ABC",而不是"我ABC+汉的半个"。
 * @author zyh
 */
public class SubChinese_Q113 {

    /**
     * @param input  需要截取的字符串
     * @param length 需要截取的字节数
     * @param encoding 字符的编码格式
     * @return 截取后的字符串
     * @throws UnsupportedEncodingException
     */
    public static String subString(String input, int length, String encoding) throws UnsupportedEncodingException {
        byte[] buf = input.getBytes(encoding);
        int characterNum = input.length();
        System.out.println("字符编码:" +  encoding +",字符串的字符个数:" + characterNum + ", 字节长度为:" + buf.length);
        //截取到当前字符时的字节数
        int total = 0;
        //应当截取到的字符的长度
        int len = 0;
        for(int i=0; i<characterNum; i++) {
            String temp = input.substring(i, i+1);
            int temp_len = temp.getBytes(encoding).length;
            total += temp_len;
            if(total<=length){
                len++;
            }
        }
        return input.substring(0, len);
    }
    
    /**
     * 参数意义同上
     */
    public static String subStr(String input, int length, String encoding) throws UnsupportedEncodingException {
            int num = 0;
            byte[] buf = input.getBytes(encoding);
            System.out.println("字符编码:" +  encoding +",字符串的字符个数:" + input.length() + ", 字节长度为:" + buf.length);
            boolean bChineseFirstHalf = false;
            for (int i = 0; i < length; i++) {
                if (buf[i] < 0 && !bChineseFirstHalf) {
                    bChineseFirstHalf = true;
                } else {
                    num++;
                    bChineseFirstHalf = false;
                }
            }
            return input.substring(0, num);
    }
    
    public static void main(String[] args) throws UnsupportedEncodingException {
        String str = "我ABC,中<汉DEF";
        System.out.println(subString(str, 7, "UTF-8"));
        System.out.println(subStr(str, 10, "GBK"));
    }

}
执行结果:

面试题之——对包含汉字的字符串截取指定字节数