在android中将字节[]转换为十六进制字符串[重复]

Posted

技术标签:

【中文标题】在android中将字节[]转换为十六进制字符串[重复]【英文标题】:Converting byte[] to Hex string in android [duplicate] 【发布时间】:2017-04-15 21:52:53 【问题描述】:

我正在尝试将 byte[] 转换为 Hex 字符串,并将相同的 Hex 字符串转换为 byte[] 在 android 中,数据不匹配。

例如:

接收到的字节[]数据:[B@b39c86a

转换后的十六进制字符串:8be897cc3c4d9e5dd6a6bbd106d8e8d487691b56

当我解码十六进制字符串时,我得到 [B@ea6d15b,但它应该是 [B@b39c86a

我正在使用下面的代码进行转换。

public String byte2hex(byte[] a) 
        /*StringBuilder sb = new StringBuilder(a.length * 2);

        for (byte b : a)
            sb.append(String.format("%02x", b & 0xff));
        return sb.toString();*/

        String hexString = "";

        for(int i = 0; i < a.length; i++)
            String thisByte = "".format("%x", a[i]);
            hexString += thisByte;
        

        return hexString;

    
    public static byte[] hexStringToByteArray(String s) 
       /* int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) 
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        
        return data;*/

        byte[] bytes = new byte[s.length() / 2];

        for(int i = 0; i < s.length(); i += 2)
            String sub = s.substring(i, i + 2);
            Integer intVal = Integer.parseInt(sub, 16);
            bytes[i / 2] = intVal.byteValue();
            String hex = "".format("0x%x", bytes[i / 2]);
        

        return bytes;
    

【问题讨论】:

[B@b39c86a。不,那不是字节数据。这是 bytes.toString() 的值。不是字节的内容。但是你在开始你的帖子时没有向我们展示你是如何来到这个字符串的。此外,您没有显示如何调用函数以及使用哪些参数。你说'我得到',但不要显示它的代码或你如何打印/记录它。请发布完整的示例。 @greenapps 我正在使用 GATT 服务,从 onCharacteristicChanged() 表格中我收到的值是 byte[]。请在下面找到我的代码。字符串 ss= byte2hex(characteristic.getValue());字节[] bt= hexStringToByteArray(ss); Log.d(TAG,"onCharacteristicChanged UUID 1::"+ss); Log.d(TAG,"onCharacteristicChanged UUID 2:: "+bt); please find my code below.。我什至不会尝试阅读。当然,您应该在帖子中发布所有代码。这是不可读的!你喜欢看cmets里的代码吗? 【参考方案1】:

请看我的代码

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

public static String bytesToHex(byte[] bytes) 
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) 
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    
    return new String(hexChars);



public static byte[] hexStringToByteArray(String s) 
    try 

        int len = s.length();
        if(len>1) 
            byte[] data = new byte[len / 2];
            for (int i = 0 ; i < len ; i += 2) 
                data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                        + Character.digit(s.charAt(i + 1), 16));
            
            return data;
        
        else

        
            return  null;
        
    catch (Exception e)
    
        throw e;
    

【讨论】:

我试过了,还是不行 它非常适合我。不要在 logcat 中打印并进行比较。检查十六进制代码 感谢您的快速回复。刚才我试过了。我收到了 "[B@8fb633d" 和 HEX 值 "79554a4660005db0453cc82becde299e54edcff0" 。当我将 HEx 转换为 byteagin 时。我收到“[B@9740732”。实际上应该是 [B@8fb633d 而不是 "[B@9740732" 对吗?【参考方案2】:

我使用以下方法,它们可以工作。

/**
 * Converts byte array to hex string
 *
 * @param bytes The data
 * @return String represents the data in HEX string
 */
public static String byteArrayToHexString(final byte[] bytes) 
    StringBuilder sb = new StringBuilder();
    for(byte b : bytes)
        sb.append(String.format("%02x", b&0xff));
    
    return sb.toString();


/**
 * Converts hex string to byte array
 *
 * @param s The data in string
 * @return byte represents the string in bytes
 */
public static byte[] hexStringToByteArray(final String s) 
    if (s == null) 
        return (new byte[]);
    

    if (s.length() % 2 != 0 || s.length() == 0) 
        return (new byte[]);
    

    byte[] data = new byte[s.length() / 2];
    for (int i = 0; i < s.length(); i += 2) 
        try 
            data[i / 2] = (Integer.decode("0x" + s.charAt(i) + s.charAt(i + 1))).byteValue();
         catch (NumberFormatException e) 
            return (new byte[]);
        
    
    return data;

【讨论】:

【参考方案3】:

我假设您通过打印对象获得了 [B@b39c86a。 这些数字由 toString() 方法生成,不会告诉您有关数组内容的任何信息。

例如,如果您运行此代码:

    byte[] arr = new byte[]1,2,3,4;
    byte[] arr2 = new byte[4];
    for(int i=0; i < 4; i++)
        arr2[i] = arr[i];


    System.out.println("Array 1: " + arr);
    System.out.println("Array 2: " + arr2);
    System.out.println("arr.equals: " + arr.equals(arr2));
    System.out.println("Arrays.equals:  " + Arrays.equals(arr,arr2));
    System.out.printf("Contents of array 1: %s\n", Arrays.toString(arr));
    System.out.printf("Contents of array 2: %s\n", Arrays.toString(arr2));

输出例如是:

Array 1: [B@74a14482
Array 2: [B@1540e19d
arr.equals: false
Arrays.equals:  true
Contents of array 1: [1, 2, 3, 4]
Contents of array 2: [1, 2, 3, 4]

toString 方法的格式为 ClassName@hashCode。 未为特定类实现的 hashCode(与字节数组一样)。

如果您查看Javadoc,它会说:

/**
....
 * As much as is reasonably practical, the hashCode method defined by
 * class @code Object does return distinct integers for distinct
 * objects. (This is typically implemented by converting the internal
 * address of the object into an integer, but this implementation
 * technique is not required by the
 * Java&trade; programming language.)
....
*/

所以,本质上,数字不能用来判断内容是否相等。 例如,您可以使用:Arrays.equals()。

本质上,内容是相同的(数组是)。 但是,您错误地检查了特定于对象实例的内容。

您的代码仍然有一个错误:

String thisByte = "".format("%x", a[i]);

使用 %02x 代替 %x,这样可以确保输出至少为 2 位数字(当它的字节值也是最大长度为 2 时)。 (而且 String.format(..) 比 "".format(..) 更容易接受)

【讨论】:

以上是关于在android中将字节[]转换为十六进制字符串[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中将十六进制字符串转换为字节字符串? [复制]

如何在 C 中将字节数组转换为十六进制字符串?

在 C++ 中将十六进制字符串转换为字节数组

如何在 C++ 中将字节数组转换为十六进制字符串?

在 Python 中将十六进制字符串转换为字节列表

如何在 Visual C++ 中将字节数组转换为十六进制字符串?