Java中二进制字节数组与十六进制互转

java | 2019-09-13 10:02:39

java中二进制字节数组与十六进制互转的代码及思路分析
一、一贯如此,先上代码,你可以直接拿去用,后面的分析可以慢慢看

public class Test01 {  
    private static String hexStr =  "0123456789ABCDEF";  
    public static void main(String[] args){  
        String str = "二进制与十六进制互转测试";  
        String hexString = BinaryToHexString(str.getBytes());  
        System.out.println("str转换为十六进制:\n"+hexString);  
        System.out.println("将str的十六进制文件转换为二进制并转为String:\n"+new String(HexStringToBinary(hexString)));  
    }  
    /** 
     *  
     * @param bytes 
     * @return 将二进制转换为十六进制字符输出 
     */  
    public static String BinaryToHexString(byte[] bytes){  
        String result = "";  
        String hex = "";  
        for(int i=0;i<bytes.length;i++){  
            //字节高4位  
            hex = String.valueOf(hexStr.charAt((bytes[i]&0xF0)>>4));  
            //字节低4位  
            hex += String.valueOf(hexStr.charAt(bytes[i]&0x0F));  
            result +=hex;  
        }  
        return result;  
    }  
    /** 
     *  
     * @param hexString 
     * @return 将十六进制转换为字节数组 
     */  
    public static byte[] HexStringToBinary(String hexString){  
        //hexString的长度对2取整,作为bytes的长度  
        int len = hexString.length()/2;  
        byte[] bytes = new byte[len];  
        byte high = 0;//字节高四位  
        byte low = 0;//字节低四位  
        for(int i=0;i<len;i++){  
             //右移四位得到高位  
             high = (byte)((hexStr.indexOf(hexString.charAt(2*i)))<<4);  
             low = (byte)hexStr.indexOf(hexString.charAt(2*i+1));  
             bytes[i] = (byte) (high|low);//高地位做或运算  
        }  
        return bytes;  
    }  
}

二、二进制字节数组与十六进制互转的思路分析
Java中byte用二进制表示占用8位,而我们知道16进制的每个字符需要用4位二进制位来表示(23 + 22 + 21 + 20 = 15),所以我们就可以把每个byte转换成两个相应的16进制字符,即把byte的高4位和低4位分别转换成相应的16进制字符H和L,并组合起来得到byte转换到16进制字符串的结果new String(H) + new String(L)。即byte用十六进制表示只占2位。
同理,相反的转换也是将两个16进制字符转换成一个byte,原理同上。
根据以上原理,我们就可以将byte[] 数组转换为16进制字符串了,当然也可以将16进制字符串转换为byte[]数组了。
在Java中字节与十六进制的相互转换主要思想有两点: 
1、二进制字节转十六进制时,将字节高位与0xF0做"&"操作,然后再左移4位,得到字节高位的十六进制A;将字节低位与0x0F做"&"操作,得到低位的十六进制B,将两个十六进制数拼装到一块AB就是该字节的十六进制表示。 
2、十六进制转二进制字节时,将十六进制字符对应的十进制数字右移动4为,得到字节高位A;将字节低位的十六进制字符对应的十进制数字B与A做"|"运算,即可得到十六进制的二进制字节表示


三、代码中是二进制原码,但是在java中采用的是补码的形式,下面介绍下什么是补码
1、反码:
        一个数如果是正,则它的反码与原码相同;
        一个数如果是负,则符号位为1,其余各位是对原码取反;
2、补码:利用溢出,我们可以将减法变成加法
       对于十进制数,从9得到5可用减法:
       9-4=5    因为4+6=10,我们可以将6作为4的补数
       改写为加法:
       9+6=15(去掉高位1,也就是减10)得到5.
       对于十六进制数,从c到5可用减法:
       c-7=5    因为7+9=16 将9作为7的补数
       改写为加法:
       c+9=15(去掉高位1,也就是减16)得到5.
    在计算机中,如果我们用1个字节表示一个数,一个字节有8位,超过8位就进1,在内存中情况为(100000000),进位1被丢弃。
    ⑴一个数为正,则它的原码、反码、补码相同
    ⑵一个数为负,刚符号位为1,其余各位是对原码取反,然后整个数加1
- 1的原码为                10000001
- 1的反码为                11111110
                                                   + 1
- 1的补码为                11111111
0的原码为                 00000000
0的反码为                 11111111(正零和负零的反码相同)
                                          +1
0的补码为               100000000(舍掉打头的1,正零和负零的补码相同)
Integer.toHexString的参数是int,如果不进行&0xff,那么当一个byte会转换成int时,由于int是32位,而byte只有8位这时会进行补位,
例如补码11111111的十进制数为-1转换为int时变为11111111111111111111111111111111好多1啊,呵呵!即0xffffffff但是这个数是不对的,这种补位就会造成误差。
和0xff相与后,高24比特就会被清0了,结果就对了。
-------------------------------------------
Java中的一个byte,其范围是-128~127的,而Integer.toHexString的参数本来是int,如果不进行&0xff,那么当一个byte会转换成int时,对于负数,会做位扩展,举例来说,一个byte的-1(即0xff),会被转换成int的-1(即0xffffffff),那么转化出的结果就不是我们想要的了。
而0xff默认是整形,所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,结果中的高的24个比特就总会被清0,于是结果总是我们想要的。

登录后即可回复 登录 | 注册
    
关注编程学问公众号