byte数组转16进制字符串的多种方式

方式一:

 byte[] array = md.digest(data.getBytes(StandardCharsets.UTF_8));
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100), 1, 3);
        }

item是byte = 8位 

一个16进制字符用十进制表示为0~15,用二进制表示为4位。用16进制表示为0~F

0xFF是两个16进制字符 = 8位。但是在程序里默认是32位,高位补零。所以0XFF = 0000 0000 0000 0000 0000 0000 1111 1111。

& 运算符:0&1 = 0 1&1 =1 0&0 = 0

因此 item & 0XFF 表示 不改变byte的原有8位把把高位补0,生成一个32位的int值。

这么做的好处是防止item的最高位即第8位被当成负数,

例如 byte item = -29;  byte转换成int应该为227.

 下面告诉大家这两者怎么相等

首先,必须要了解几个概念:

机器数:计算机存储的二进制的形式数值。带有正负号,最高位是1表示负数,最高位是0表示正数。例如上面的item 表示为 -29 ,这个值的机器数为1001 1101,转换成2进制=157 机器数是形式值,不是真实的值。

机器数的真值表示真正代表的值,item的真值是带有符号位的-29.

 

补码、反码、原码是计算机进行储存采用的编码方式。

计算机默认采用补码的编码方式。数据储存到计算机的过程,是原码转换成补码的过程。

原码:符号位加上真值的值。 1的原码 = 0000 0001 -1的原码 = 1000 0001 。原码是人类最容易理解和计算的方式。

反码:正数的反码是其本身,负数的反码是基于原码除了符号位不变,其他位取反。1的反码 = 0000 0001 ,-1的反码 = 1111 1110。 负数的反码人类无法直观的看出来。

补码:正数的补码是其本身,负数的补码是基于原码除了符号位不变,其他位取反+1。1的补码 = 0000 0001 -1的补码 = 1111 1111。负数的补码人类也无法直观的看出来

因为计算机只会用加法,所以1-1 = 1+ (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]反 + [1111 1110] 反= [1111 1111]反 = [1000 0000] = -0。 用反码计算,真值部分正确的,但是-0没有任何意义。而且0会有[0000 0000][1000 0000]两种表示方式。

于是采用了补码进行编码,所以1-1 = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111] 补 = [1 0000 0000]补 (高位不计算) = [0000 0000] = 0 所以-0就不存在了。而且[1000 0000]补 可以用来表示 -128 ,但是-128的的原码计算是0,所以-128没有原码和反码。

 

此,item的机器真值是-29,在计算机的编码方式:{1001 1101]原= [1110 0011]补 = 机器保存的二进制编码形式值 = 227.

byte转换为int,则高位会补0 ,由补码的负数变成了正数。而16进制应该是采用补码进行计算,即16进制也是以补码的形式存储。

如若不然,强行转换 int会被赋予-29的值,在计算机里是计算解码:补码[1001 1101] 补 = [1110 0011]原 = -99 ,得出是不正确的 数据。

正确的转换方式是:高位补0  方式为item&0xFF

 

(item&0xFF)|0x100:0x100的原因是0~15位会生成一个字符0~F,问题是最高位是0000 则不会生成高位的字符,0000 1110 = 0e 实际生成 e。

如果想要2位对齐,就需要前面补0。

所以0x100是在最高位前面补一个1,然后在截断第一位 ,例如0000 1110 | 0x100 = 0001 0000 1110 = 10e 实际生成 10e ,截断后 0e,完成了格式化。

备注:

|0x100 也可以是 |0x200 |0x300 或 +0x100 +0x200 

 

还有另一种方法

   for (byte item : array) {
            s2.append(String.format("%02x",item&0xFF));
        }

用String.format 格式化控制,以十六进制输出,2为指定的输出字段的宽度.如果位数小于2,则左端补0。

 

posted @ 2023-07-26 10:36  IT知识生产小店铺  阅读(4778)  评论(0编辑  收藏  举报