zoukankan      html  css  js  c++  java
  • Java-byte[]与16进制字符串互转

    转自: http://www.cnblogs.com/freeliver54/archive/2012/07/30/2615149.html 

    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[]数组了。

        /**

    1.  * Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串。   
    2.  * @param src byte[] data   
    3.  * @return hex string   
    4.  */      
    5. public static String bytesToHexString(byte[] src){   
    6.     StringBuilder stringBuilder = new StringBuilder("");   
    7.     if (src == null || src.length <= 0) {   
    8.         return null;   
    9.     }   
    10.     for (int i = 0; i < src.length; i++) {   
    11.         int v = src[i] & 0xFF;   
    12.         String hv = Integer.toHexString(v);   
    13.         if (hv.length() < 2) {   
    14.             stringBuilder.append(0);   
    15.         }   
    16.         stringBuilder.append(hv);   
    17.     }   
    18.     return stringBuilder.toString();   
    19. }   
    20. /**  
    21.  * Convert hex string to byte[]  
    22.  * @param hexString the hex string  
    23.  * @return byte[]  
    24.  */  
    25. public static byte[] hexStringToBytes(String hexString) {   
    26.     if (hexString == null || hexString.equals("")) {   
    27.         return null;   
    28.     }   
    29.     hexString = hexString.toUpperCase();   
    30.     int length = hexString.length() / 2;   
    31.     char[] hexChars = hexString.toCharArray();   
    32.     byte[] d = new byte[length];   
    33.     for (int i = 0; i < length; i++) {   
    34.         int pos = i * 2;   
    35.         d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));   
    36.     }   
    37.     return d;   
    38. }   
    39. /**  
    40.  * Convert char to byte  
    41.  * @param c char  
    42.  * @return byte  
    43.  */  
    44.  private byte charToByte(char c) {   
    45.     return (byte) "0123456789ABCDEF".indexOf(c);   
    46. }  
    1. //将指定byte数组以16进制的形式打印到控制台   
    2. public static void printHexString( byte[] b) {     
    3.    for (int i = 0; i < b.length; i++) {    
    4.      String hex = Integer.toHexString(b[i] & 0xFF);    
    5.      if (hex.length() == 1) {    
    6.        hex = '0' + hex;    
    7.      }    
    8.      System.out.print(hex.toUpperCase() );    
    9.    }    
    10.   
    11. }  

    java中byte转换int时为何与0xff进行与运算

    在剖析该问题前请看如下代码

    1. public static String bytes2HexString(byte[] b) {   
    2.   String ret = "";   
    3.   for (int i = 0; i < b.length; i++) {   
    4.    String hex = Integer.toHexString(b[ i ] & 0xFF);   
    5.    if (hex.length() == 1) {   
    6.     hex = '0' + hex;   
    7.    }   
    8.    ret += hex.toUpperCase();   
    9.   }   
    10.   return ret;   
    11. }  

     
    上面是将byte[]转化十六进制的字符串,注意这里b[ i ] & 0xFF将一个byte和 0xFF进行了与运算,然后使用Integer.toHexString取得了十六进制字符串,可以看出
    b[ i ] & 0xFF运算后得出的仍然是个int,那么为何要和 0xFF进行与运算呢?直接 Integer.toHexString(b[ i ]);,将byte强转为int不行吗?答案是不行的.

    其原因在于:
    1.byte的大小为8bits而int的大小为32bits
    2.java的二进制采用的是补码形式

    在这里先温习下计算机基础理论

    byte是一个字节保存的,有8个位,即8个0、1。
    8位的第一个位是符号位, 
    也就是说0000 0001代表的是数字1 
    1000 0000代表的就是-1 
    所以正数最大位0111 1111,也就是数字127 
    负数最大为1111 1111,也就是数字-128

    上面说的是二进制原码,但是在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,于是结果总是我们想要的。

    ----------- 赠人玫瑰,手有余香     如果本文对您有所帮助,动动手指扫一扫哟   么么哒 -----------


    未经作者 https://www.cnblogs.com/xin1006/ 梦相随1006 同意,不得擅自转载本文,否则后果自负
  • 相关阅读:
    Java实现各种内部排序算法
    Java实现堆排序(大根堆)
    Java对象的序列化和反序列化
    Java实现链式存储的二叉查找树(递归方法)
    337. House Robber III(包含I和II)
    318. Maximum Product of Word Lengths
    114. Flatten Binary Tree to Linked List
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    96. Unique Binary Search Trees(I 和 II)
  • 原文地址:https://www.cnblogs.com/xin1006/p/7367516.html
Copyright © 2011-2022 走看看