1

I am trying to convert byte[] to Hex string and same Hex string to byte[] in android , data got mismatched.

Ex :

Received byte[] data : [B@b39c86a

converted Hex string : 8be897cc3c4d9e5dd6a6bbd106d8e8d487691b56

When I decode the hex string, I am getting [B@ea6d15b, but its should be [B@b39c86a

I am using below code to convert.

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;
    }
Nikhil
  • 3,711
  • 8
  • 32
  • 43
karthik selvaraj
  • 467
  • 5
  • 8
  • 21
  • 1
    `[B@b39c86a`. No that is NOT the byte data. that is the value for bytes.toString(). NOT the contents of the bytes. But you start your post wrong by not showing us how you came to this string. Further you are not showing how you call your functions and which parameters you use. And you say 'i am getting' but do do not show the code for it or how you print/log it. Please post complete example. – greenapps Dec 01 '16 at 10:19
  • @greenapps i am using GATT service, form onCharacteristicChanged() i am receiving value as byte[]. please find my code below. String ss= byte2hex(characteristic.getValue()); byte[] bt= hexStringToByteArray(ss); Log.d(TAG,"onCharacteristicChanged UUID 1:: "+ss); Log.d(TAG,"onCharacteristicChanged UUID 2:: "+bt); – karthik selvaraj Dec 01 '16 at 10:36
  • `please find my code below.`. I will not even try to read that. You should post all code in your post of course. This is unreadable! Do you like to read code in comments? – greenapps Dec 01 '16 at 10:48

3 Answers3

5

I use the following and they work.

/**
 * 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;
}
fbwnd
  • 687
  • 6
  • 12
4

I assume you are getting the [B@b39c86a by printing the object. Those numbers are generated by the toString() method and do not tell you anything about the contents of the array.

For example if you run this code:

    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));

The output would for example be:

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]

the toString method is in the format ClassName @ hashCode. The hashCode when not implemented for a specific class (As is the case for a byte-array).

If you look at the Javadoc it states:

/**
....
 * 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.)
....
*/

So, in essence, the numbers can not be used to determine if the content is equal. You could for example use: Arrays.equals().

In essence, the contents are the same (the arrays are). You are however making the mistake of checking something that is object instance specific.

Your code does however still have one mistake:

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

Instead of %x use %02x, this ensures that the output is at least 2 digits (and when its a byte value also a max length of 2). (Also String.format(..) is a bit more accepted than "".format(..))

user254948
  • 1,036
  • 6
  • 14
-1

Please look on my code

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;
    }
}
noobEinstien
  • 3,147
  • 4
  • 24
  • 42