Java十六进制字符串与二进制数组互转、&0xff的作用

十六进制字符串转字节数组

/**
     * 功能: 十六进制字符串转字节数组
     * @param hexString 十六进制字符串
     * @return 字节数组
     */
    public static byte[] convertHexStringToBytes(String hexString){
        //判空
        if(hexString == null || hexString.length() == 0) {
            return null;
        }

        //合法性校验
        if(!hexString.matches("[a-fA-F0-9]*") || hexString.length() % 2 != 0) {
            return null;
        }

        //计算
        int mid = hexString.length() / 2;
        byte[]bytes = new byte[mid];
        for (int i = 0; i < mid; i++) {
            bytes[i] = Integer.valueOf(hexString.substring(i * 2, i * 2 + 2), 16).byteValue();
        }

        return bytes;
    }

字节数组转十六进制字符串

    /**
     * 字节数组转16进制数
     * @param bytes 字节数组
     * @return 返回值
     */
    public static String convertBytesToHexString(byte[]bytes) {
        StringBuilder res = new StringBuilder("");
        for (byte aByte : bytes) {
            String temp = Integer.toHexString(aByte & 0xff);
            if (temp.length() == 1) {
                temp = '0' + temp;
            }
            res.append(temp);
        }
        return res.toString().toUpperCase();
    }

整数转化为十六进制字符串

 /**
     * 功能:将整数转化为合法的十六进制字符串
     * @param source 整数
     * @param len 至少占多少个字节
     * @return 十六进制数
     *
     * 说明:为什么要有len?
     * 某些场景需要指定大小的二进制字符串(这里的大小指的是转化为字节数组后所占大小)
     * 例如,现在需要把1这个整数转化为十六进制数,
     * 如果len为1,结果为 01
     * 如果len为2,结果为 0001
     *
     * 但是len不限制大小,比如len设置为1,source为125120,那么结果仍然为1e8c0,
     * 不会截断结果
     */
    public static String convertIntToHexString(int source, int len) {
        //一个字节占两位,所以要乘以2
        len <<= 1;
        StringBuilder res = new StringBuilder(Integer.toHexString(source));
        int comp = len - res.length();

        //位数不足,需要补0
        if(comp > 0) {
            for (int i = 0; i < comp; i++) {
                res.insert(0, "0");
            }
        }

        return res.toString();
    }

个人理解

上文提及的“合法十六进制字符串”指的是什么?

需要满足如下条件:

1、只能包含数字以及字母ABCDEF(包含大小写)

2、字符的个数必须是双数,比如“1”只能写成“01”

&0xff 到底有什么含义?

首先我们先了解一下基本作用

1 & 0 = 0

1 & 1 = 1

0 & 0 = 0

计算机中二进制数都是以补码的形式存在

a & 0xff 表示取 a 补码的后八位。

16进制字符串的范围是 0x00 到 0xff,0到255

java中的byte是有符号的,一个byte表示的范围是  -128到127。

而在这里,我们不需要byte的符号属性,只需要它老老实实的表示0到255即可,所以不得不将128到255之间的数据做一个映射。

换句话说,11111111(补码), 如果最高位作为符号位, 它是-1,如果不作为符号位,那就能表示255.

    public static void main(String[] args) {
          byte a = -1;
          int b = a & 0xff;
          System.out.println(a);
          System.out.println(b);
    }

结果是:

-1
255

a & 0xff的返回值是int,也就是说,将a这个字节的补码原封不动的拿出来,放到int中。

因为int 是四个字节,我们现在只用了两个字节,自然触碰不到符号位,这么一操作,就可以将 -1 映射成 255。

这样就可以理解字节转字符串中的这个转换了:

Integer.toHexString(aByte & 0xff);

简而言之,我们确实需要存256个数,但是范围是0-255,而不是 -128-127,因为java不支持unsigned byte这种数据类型,所以我们需要借助容量更大的int完成这一转换。

换句话说,如果java支持无符号byte,就不需要做这种转换了。(C#中的byte就是没有符号的,sbyte才是有符号的)

关于原码、补码、反码的相关概念,推荐文章:  https://zhuanlan.zhihu.com/p/91967268

如有错误,恳请批评指正!

原文地址:https://www.cnblogs.com/phdeblog/p/14000915.html