JAVA十六进制操作工具类

物联网类的系统开发,涉及与低功耗终端设备间的对接,经常会用到16进制之间转化问题,如byte[]转为16进制字符串,BCD码转字节数组等。本工具类依赖hutool,请注意先导入此包。

import cn.hutool.core.util.StrUtil;

import java.util.Base64;
import java.util.Locale;

public class HexConvertUtil {

    /**
     * 一个字节包含位的数量 8
     */
    private static final int BITS_OF_BYTE = 8;

    /**
     * 多项式
     */
    private static final int POLYNOMIAL = 0xA001;

    /**
     * 初始值
     */
    private static final int INITIAL_VALUE = 0xFFFF;

    private final static char[] mChars = "0123456789ABCDEF".toCharArray();
    private final static String mHexStr = "0123456789ABCDEF";

    /**
     * 检查16进制字符串是否有效
     *
     * @param sHex String 16进制字符串
     * @return boolean
     */
    public static boolean checkHexStr(String sHex) {
        String sTmp = sHex.trim().replace(" ", "").toUpperCase(Locale.US);
        int iLen = sTmp.length();

        if (iLen > 1 && iLen % 2 == 0) {
            for (int i = 0; i < iLen; i++)
                if (!mHexStr.contains(sTmp.substring(i, i + 1)))
                    return false;
            return true;
        } else
            return false;
    }

    /**
     * 字符串转换成十六进制字符串
     *
     * @param str String 待转换的ASCII字符串
     * @return String 每个Byte之间空格分隔,如: [61 6C 6B]
     */
    public static String str2HexStr(String str) {
        StringBuilder sb = new StringBuilder();
        byte[] bs = str.getBytes();

        for (int i = 0; i < bs.length; i++) {
            sb.append(mChars[(bs[i] & 0xFF) >> 4]);
            sb.append(mChars[bs[i] & 0x0F]);
            sb.append(' ');
        }
        return sb.toString().trim();
    }

    /**
     * 十六进制字符串转换成 ASCII字符串
     *
     * @param hexStr String Byte字符串
     * @return String 对应的字符串
     */
    public static String hexStr2Str(String hexStr) {
        hexStr = hexStr.trim().replace(" ", "").toUpperCase(Locale.US);
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int iTmp;
        for (int i = 0; i < bytes.length; i++) {
            iTmp = mHexStr.indexOf(hexs[2 * i]) << 4;
            iTmp |= mHexStr.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (iTmp & 0xFF);
        }
        return new String(bytes);
    }

    /**
     * bytes转换成十六进制字符串
     *
     * @param b    byte[] byte数组
     * @param iLen int 取前N位处理 N=iLen
     * @return String 每个Byte值之间空格分隔
     */
    public static String byte2HexStr(byte[] b, int iLen) {
        StringBuilder sb = new StringBuilder();
        for (int n = 0; n < iLen; n++) {
            sb.append(mChars[(b[n] & 0xFF) >> 4]);
            sb.append(mChars[b[n] & 0x0F]);
            sb.append(' ');
        }
        return sb.toString().trim().toUpperCase(Locale.US);
    }

    /**
     * bytes字符串转换为Byte值
     *
     * @param src String Byte字符串,每个Byte之间没有分隔符(字符范围:0-9 A-F)
     * @return byte[]
     */
    public static byte[] hexStr2Bytes(String src) {
        /*对输入值进行规范化整理*/
        src = src.trim().replace(" ", "").toUpperCase(Locale.US);
        //处理值初始化
        int m, n;
        int iLen = src.length() / 2; //计算长度
        byte[] ret = new byte[iLen]; //分配存储空间

        for (int i = 0; i < iLen; i++) {
            m = i * 2 + 1;
            n = m + 1;
            ret[i] = (byte) (Integer.decode("0x" + src.substring(i * 2, m) + src.substring(m, n)) & 0xFF);
        }
        return ret;
    }

    /**
     * String的字符串转换成unicode的String
     *
     * @param strText String 全角字符串
     * @return String 每个unicode之间无分隔符
     * @throws Exception
     */
    public static String strToUnicode(String strText)
            throws Exception {
        char c;
        StringBuilder str = new StringBuilder();
        int intAsc;
        String strHex;
        for (int i = 0; i < strText.length(); i++) {
            c = strText.charAt(i);
            intAsc = (int) c;
            strHex = Integer.toHexString(intAsc);
            if (intAsc > 128)
                str.append("\\u");
            else // 低位在前面补00
                str.append("\\u00");
            str.append(strHex);
        }
        return str.toString();
    }

    /**
     * unicode的String转换成String的字符串
     *
     * @param hex String 16进制值字符串 (一个unicode为2byte)
     * @return String 全角字符串
     */
    public static String unicodeToString(String hex) {
        int t = hex.length() / 6;
        int iTmp;
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < t; i++) {
            String s = hex.substring(i * 6, (i + 1) * 6);
            // 将16进制的string转为int
            iTmp = (Integer.valueOf(s.substring(2, 4), 16) << 8) | Integer.valueOf(s.substring(4), 16);
            // 将int转换为字符
            str.append(new String(Character.toChars(iTmp)));
        }
        return str.toString();
    }

    /**
     * 将bytes转为16进制string
     *
     * @param byteArray
     * @return
     */
    public static String byteArrayToHexStr(byte[] byteArray) {
        if (byteArray == null) {
            return null;
        }
        char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[byteArray.length * 2];
        for (int j = 0; j < byteArray.length; j++) {
            int v = byteArray[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    /**
     * 将指定字符串src,以每两个字符分割转换为16进制形式
     * 如:"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF, 0xD9}
     *
     * @param src String
     * @return byte[]
     */
    public static byte[] hexString2Bytes(String src) {

        byte[] ret = new byte[src.length() / 2];
        byte[] tmp = src.getBytes();
        for (int i = 0; i < tmp.length / 2; i++) {
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return ret;
    }

    /**
     * 将两个ASCII字符合成一个字节;
     * 如:"EF"--> 0xEF
     *
     * @param src0 byte
     * @param src1 byte
     * @return byte
     */
    public static byte uniteBytes(byte src0, byte src1) {
        byte _b0 = Byte.decode("0x" + new String(new byte[]{src0})).byteValue();
        _b0 = (byte) (_b0 << 4);
        byte _b1 = Byte.decode("0x" + new String(new byte[]{src1})).byteValue();
        byte ret = (byte) (_b0 ^ _b1);
        return ret;
    }

    /**
     * 拆分数组
     *
     * @param start  开始下标
     * @param length 拆分长度
     * @param bytes  需要拆分的数组
     * @return
     */
    public static byte[] split(int start, int length, byte[] bytes) {
        byte[] by = new byte[length];
        System.arraycopy(bytes, start, by, 0, length);
        return by;
    }

    /**
     * bytes转换成十六进制字符串 不带空格
     *
     * @param b byte数组
     * @return String 每个Byte值之间空格分隔 如: 616C6B
     */
    public static String bytes2HexStr1(byte[] b) {
        String stmp;
        StringBuilder sb = new StringBuilder("");
        for (int n = 0; n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0xFF);
            sb.append((stmp.length() == 1) ? "0" + stmp : stmp);
        }
        return sb.toString().toUpperCase().trim();
    }

    /**
     * 将字节数组合并为字符串.<br>
     * 本方法为取出每一位字节,直接作为字符处理,而不是作为ASCII值<br>
     * 例如:字节49->字符49,而不是字节49->字符1(字符1的ASCII值是49)
     *
     * @param byteArray
     * @return
     */
    public static String byteArray2String(byte[] byteArray) {

        // 合并后的字符串
        StringBuffer sb = new StringBuffer(byteArray.length);
        // 遍历字节数组
        for (int i = 0, length = byteArray.length; i < length; i++) {

            sb.append(byteArray[i]);
        }

        return sb.toString();
    }

    /**
     * BCD码转字节数组
     *
     * @param bcd bcd码
     * @return
     */
    public static byte[] bcd2ByteArray(byte[] bcd) {

        // 转换后字节数组
        byte[] byteArray = new byte[bcd.length * 2];
        // 遍历BCD码
        for (int i = 0, length = bcd.length; i < length; i++) {

            byteArray[i * 2] = (byte) ((bcd[i] & 0xf0) >> 4);
            byteArray[i * 2 + 1] = (byte) (bcd[i] & 0x0f);
        }

        return byteArray;
    }

    /**
     * 将字节数组(0<长度<=8)合并为长整型
     *
     * @param byteArray
     * @return
     */
    public static long byteArray2Long(byte[] byteArray) {

        // 字节数组长度
        int length = byteArray.length;

        if (length == 0) {
            throw new RuntimeException("运行异常");
        } else if (length > 8) {
            throw new RuntimeException("运行异常");
        } else {
            // 获取最末位的字节
            long l = byte2Long(byteArray[length - 1]);

            // 遍历字节数组,从倒数第二位向前
            for (int index = length - 1; index > 0; index--) {

                // 数组的第(index-1)位,要向左移(length-index)字节
                l = l | byte2Long(byteArray[index - 1]) << ((length - index) * 8);
            }

            return l;
        }
    }

    public static long byte2Long(byte b) {

        return (b & 0xff);
    }

    /**
     * 字节数组转为普通字符串(ASCII对应的字符)
     *
     * @param bytearray byte[]
     * @return String
     */
    public static String bytetoString(byte[] bytearray) {
        String result = "";
        char temp;

        int length = bytearray.length;
        for (int i = 0; i < length; i++) {
            temp = (char) bytearray[i];
            result += temp;
        }
        return result;
    }

    /**
     * 将字节数组(0<长度<=4)合并为整型
     *
     * @param byteArray
     * @return
     */
    public static int byteArray2Int(byte[] byteArray) {

        // 字节数组长度
        int length = byteArray.length;

        if (length == 0) {
            throw new RuntimeException("运行异常");
        } else if (length > 4) {
            throw new RuntimeException("运行异常");
        } else {
            // 获取最末位的字节
            int i = byte2Int(byteArray[length - 1]);

            // 遍历字节数组,从倒数第二位向前
            for (int index = length - 1; index > 0; index--) {

                // 数组的第(index-1)位,要向左移(length-index)字节
                i = i | (byte2Int(byteArray[index - 1]) << ((length - index) * 8));
            }

            return i;
        }
    }

    /**
     * 将无符号字节(即8位均为数据的字节)转换为有符号的整型;
     *
     * @param b 无符号字节
     * @return
     */
    public static int byte2Int(byte b) {

        return (b & 0xff);
    }

    /**
     * 字节数组转BCD码,字节数组长度必须为2的倍数
     *
     * @param byteArray
     * @return
     */
    public static byte[] byteArray2BCD(byte[] byteArray) {

        // 字节数组长度
        int byteArrayLength = byteArray.length;
        // 若长度不为2的倍数,则抛出异常
        if (byteArrayLength % 2 != 0) {
            throw new RuntimeException("运行异常");
        }

        // BCD码
        byte[] bcd = new byte[byteArrayLength / 2];
        // 遍历字节数组
        for (int i = 0, length = bcd.length; i < length; i++) {

            // 前字节向左位移4位,与上后字节
            bcd[i] = (byte) (((byte) (byteArray[i * 2] << 4)) | (byteArray[i * 2 + 1]));
        }

        return bcd;
    }

    /**
     * 将字符串拆分为字节数组.
     * 本方法为取出每一个字符,将其直接转为byte,而非使用ASCII值进行转换
     * 例如:字符1->字节1,而不是字符1->字节49(字符1的ASCII值是49)
     *
     * @param str
     * @return
     */
    public static byte[] string2ByteArray(String str) {

        // 拆分后的字节数组
        byte[] byteArray = new byte[str.length()];
        // 遍历字符串每一个字符
        for (int i = 0, length = str.length(); i < length; i++) {

            byteArray[i] = Byte.valueOf(str.charAt(i) + "");
        }

        return byteArray;
    }

    /**
     * 将整型拆分为长度为4的字节数组
     *
     * @param i
     * @return
     */
    public static byte[] int2ByteArray(int i) {

        // 拆分后的字节数组
        byte[] byteArray = new byte[4];
        // 数组长度
        int length = byteArray.length;

        // 遍历数组
        for (int index = 1; index <= length; index++) {

            // 数组的第(index-1)位,要向右移(length-index)字节
            byteArray[index - 1] = (byte) (i >> ((length - index) * 8));
        }

        return byteArray;
    }

    /**
     * 将长整型拆分为长度为8的字节数组
     *
     * @param l
     * @return
     */
    public static byte[] long2ByteArray(long l) {

        // 拆分后的字节数组
        byte[] byteArray = new byte[8];
        // 数组长度
        int length = byteArray.length;

        // 遍历数组
        for (int index = 1; index <= length; index++) {

            // 数组的第(index-1)位,要向右移(length-index)字节
            byteArray[index - 1] = (byte) (l >> ((length - index) * 8));
        }

        return byteArray;
    }

    public static byte[] intToBytes(int source, int length) {
        byte[] b = new byte[length];
        for (int i = 0; i < length; i++) {
            b[i] = (byte) (source >> 8 * (length - i - 1) & 0xFF);
        }
        return b;
    }

    /**
     * base64字符串转16进制字符串
     *
     * @param base64Str
     * @return
     */
    public static byte[] base64ToHexByte(String base64Str) {
        if (StrUtil.isEmpty(base64Str)) {
            throw new RuntimeException("base64字符串不能为空!");
        }
        return Base64.getDecoder().decode(base64Str);
    }

    public static String byteArrToBinStr(byte[] b) {
        StringBuilder result = new StringBuilder();
        for (byte value : b) {
            String str = Long.toString(value & 0xff, 2);
            if (str.length() < 8) {
                StringBuilder zeroStr = new StringBuilder();
                for (int i = 0; i < (8 - str.length()); i++) {
                    zeroStr.append(0);
                }
                str = zeroStr + str;
            }
            result.append(str).append(",");
        }
        return result.substring(0, result.length() - 1);
    }

    public static int crc16(byte[] bytes) {
        int res = INITIAL_VALUE;
        for (int data : bytes) {
            res = res ^ data;
            for (int i = 0; i < BITS_OF_BYTE; i++) {
                res = (res & 0x0001) == 1 ? (res >> 1) ^ POLYNOMIAL : res >> 1;
            }
        }
        return revert(res);
    }

    private static int revert(int src) {
        int lowByte = (src & 0xFF00) >> 8;
        int highByte = (src & 0x00FF) << 8;
        return lowByte | highByte;
    }

    public static byte crc8(byte[] data) {
        byte crc = 0;
        for (byte datum : data) {
            crc ^= datum;
            for (int i = 0; i < 8; i++) {
                if ((crc & 0x80) != 0) {
                    crc = (byte) ((crc) << 1);
                    crc ^= (byte) 0x107;
                } else {
                    crc = (byte) ((crc) << 1);
                }
            }
        }
        return crc;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值