Java自定义的读取UTF-8字符集的字节工具

一、主要作用

实现UTF-8字节序列的读取,转成String字符串;

二、主要思路

1、根据UTF-8每个字节的前缀来确定一个字符的字节组成部分;

2、把属于一个字符的所有连续字节读取,提取关键字节,相加或者属于一个字符的唯一整数;

3、把这个整数强制转成char类型,就获得了字符值;


三、主要代码如下


public class StringUtil{
    /**
     * 使用UTF-8的方法读取字符串。
     *
     * @param source
     * @return
     */
    public static String toStringByUTF8(byte[] source) {

        /*
        UTF-8的规则如下:
            根据前缀,判断这个字符由几个字节组成;x代表字符的二进制序列,依次填入
            0xxxxxxx    一个字节,表示ASCII码
            110xxxxx 10xxxxxx       前缀为110,代表连续的两个字节,表示一个字符
            1110xxxx 10xxxxxx 10xxxxxx       前缀为1110,代表连续的三个字节,表示一个字符
            11110xxx 10xxxxxx 10xxxxxx 10xxxxxx      前缀为11110,代表连续的四个字节,表示一个字符
         */

        // 定义下标变量
        int index = 0;

        // 定义个数,1代表一个字节,4代表四个字节。
        int size = 1;

        // 判断是否处理进行字符转换,说明某个字符的所有字节都获取到了。
        boolean isEnd = false;

        // 存放最终的字符数据
        StringBuffer result = new StringBuffer();

        // 存放某个字节的二进制码
        StringBuffer buffer = new StringBuffer();

        while (true) {

            // 如果超出范围,跳出循环
            if (index >= source.length) {
                break;
            }

            // 转成二进制的字符串形式
            String bin = Integer.toBinaryString(source[index] & 0xFF);

            // 位数不够8位要左边补零
            if (bin.length() < 8) {
                String temp = getZeros(8 - bin.length());
                bin = temp.concat(bin);
            }

            // 根据前缀判断类别
            if (bin.charAt(0) == '0') {
                size = 1;
                buffer.append(bin.substring(1));
                // 设置可以直接获取
                isEnd = true;
            } else if (bin.startsWith("110")) {
                size = 2;
                buffer.append(bin.substring(3));
            } else if (bin.startsWith("1110")) {
                size = 3;
                buffer.append(bin.substring(4));
            } else if (bin.startsWith("11110")) {
                size = 4;
                buffer.append(bin.substring(5));
            } else if (bin.startsWith("111110")) {
                size = 4;
                buffer.append(bin.substring(6));
            } else if (bin.startsWith("10")) {
                // 添加二进制数据码
                buffer.append(bin.substring(2));
                size--;
                if (size == 1) {
                    isEnd = true;
                }
            }
            // 判断是否进行转换一次
            if (isEnd) {
                // 转换成char类型,存入结果缓冲里。
                result.append((char) Integer.parseInt(buffer.toString(), 2));

                // 清空buffer
                buffer.delete(0, buffer.length());

                // 设置标志位false
                isEnd = false;
            }
            index++;
        }
        return result.toString();
    }

    /**
     * 传入字符串,返回它的UTF-8字节流数组
     *
     * @param str
     * @return
     */
    public static byte[] getBytesUTF8(String str) {
        // 字节数组输出流
        ByteArrayOutputStream stream = new ByteArrayOutputStream();

        // 定义索引
        int index = 0;

        // 转换成字符数组
        char[] charArray = str.toCharArray();

        // 中间变量
        char temp = ' ';

        // 存放一个字节的二进制码
        String bitStr = "";

        while (true) {
            if (index >= charArray.length){
                break;
            }

            // 获得某个字符
            temp = charArray[index];

            // 获得二进制字符码
            String binaryStr = Integer.toBinaryString(temp);

            if (temp >= 0x00 && temp <= 0x7F) {
                // 转换成整数,写入字节数组输出流
                stream.write(Integer.parseUnsignedInt(binaryStr, 2));
            } else if (temp >= 0x80 && temp <= 0x7FF) {
                bitStr = formatBinString(binaryStr, 11);
                stream.write(Integer.parseUnsignedInt("110" + bitStr.substring(0, 5), 2));
                stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(5), 2));

            } else if (temp >= 0x800 && temp <= 0xFFFF) {
                bitStr = formatBinString(binaryStr, 16);
                stream.write(Integer.parseUnsignedInt("1110" + bitStr.substring(0, 4), 2));
                stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(4, 10), 2));
                stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(10), 2));

            } else if (temp >= 0x10000 && temp <= 0x10FFFF) {
                bitStr = formatBinString(binaryStr, 21);
                stream.write(Integer.parseUnsignedInt("11110" + bitStr.substring(0, 3), 2));
                stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(3, 9), 2));
                stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(9, 15), 2));
                stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(15), 2));
            }
            index++;
        }

        // 返回字节数组
        return stream.toByteArray();
    }

    /**
     * 格式化字符串:
     * <p>
     *    如果多余,去掉左边的0;
     *    如果没有达到位数,左边加0;
     */
    public static String formatBinString(String source, int length) {

        String result = "";

        if (source.length() == length){
            result = source;
        } else if (source.length() < length){
            // 拼接数字0,返回
            result = getZeros(length - source.length()).concat(source);
        } else {
            // 获得多余的个数
            int overflow = source.length() - length;

            // 取得子字符串返回
            result = source.substring(overflow);
        }
        return result;
    }

    /**
     * 返回指定位数由0拼接成的字符串
     *
     * @param count
     * @return
     */
    public static String getZeros(int count) {
        String result = "";
        for (int i = 0; i < count; i++) {
            result += "0";
        }
        return result;
    }

    /**
     * 按照Unicode的格式读取一个字符,占用两个字节
     *
     * @param source
     * @return
     */
    private static char toUnicodeChar(byte[] source) {

        int length = source.length;
        System.out.println("长度:" + length);

        int result = 0;
        int temp = 0;

        for (int k = length - 1; k >= 0; k--){

            temp = (source[k] & 0xFF);
            temp = temp << (8 * k);
            result = result + temp;
        }

        System.out.println(source[0] & 0xFF);
        System.out.println(source[1] & 0xFF);
        System.out.println(source[2] & 0xFF);
        System.out.println(source[3] & 0xFF);

        return (char)result;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值