0

I try to convert byte[] to long, but I got java.lang.NumberFormatException.

this is the byte array I wanna convert to long

byte[] data = new byte[]{(byte) 0xDB, (byte) 0xA7, 0x53, (byte) 0xF8, (byte) 0xA8, 0x0C, 0x66, 0x8};

Then I try to convert that data to hex string with this algorithm

public static String hexStringFromHexData(byte[] data){
        StringBuilder hexString = new StringBuilder();

        for (byte subData : data) {
            String temp = Integer.toHexString(subData & 0xFF);
            if (temp.length() == 1) {
                temp = "0" + temp;
            }
            hexString.append(temp);
        }

        return hexString.toString();
    }

So I got the hexstring like this "dba753f8a80c6608"

with that hexstring I convert it to long like below

String hexstring = "dba753f8a80c6608";
Long value = Long.parseLong(hexString.trim(), 16);

It throw NumberFormatException because the hexstring is exceed 7fffffffffffffff (Long.MAX_VALUE).

The right hexstring have to be like this "DBA753F8A80C668" and with this hexstring is able to convert it to this long value 989231983928329832L without get exception.

we can try convert this long value back to hex string

long value = 989231983928329832L
String hexString = Long.toHexString(value);

the we got the hexstring like this "DBA753F8A80C668" and if we convert it to byte array it will be same with byte array data like above.

So how do I convert the byte[] data above to hex string like this "DBA753F8A80C668"?

Is it any other algorithm for convert byte[] data above and return correct long value like this 989231983928329832L?

======================================================================

simple step to reproduce:

  1. 989231983928329832 to convert it to byte[] data

  2. convert byte[] data back to long value 989231983928329832L

jefry jacky
  • 799
  • 7
  • 11
  • I don't get what your problem is here. Is it the NumberFormatException for certain values? Besides that your code seems to be doing exactly what you are describing. – André Stannek Jul 28 '17 at 08:54
  • I can't convert that byte[] data to long value, the expected long value is 989231983928329832L as we can see at http://www.binaryhexconverter.com/decimal-to-hex-converter – jefry jacky Jul 28 '17 at 08:57
  • @jefryjacky you have two different hex strings in your question. One has a 0 before the 8 in the end. If you remove that 0 it works just fine. – André Stannek Jul 28 '17 at 09:02
  • @JeremyGrand it is not the case sensitive problem. the hex string produce from the method hexStringFromHexData ("dba753f8a80c6608") is false, the right hex string I expect is "dba753f8a80c668". – jefry jacky Jul 28 '17 at 09:10
  • @AndréStannek "dba753f8a80c6608" is the value return from hexStringFromHexData method, "DBA753F8A80C668" is the value I expected to return. – jefry jacky Jul 28 '17 at 09:12
  • 2
    if you convert **0x0C** into string you expect the result **0C**,if you convert **0x8** into string you expect the result **8**;That will not work if you convert **byte** since **0x0C** == **0xC** as well as **0x8** == **0x08** – Martin Frank Jul 28 '17 at 09:18
  • Use `ByteBuffer`. `long longValue = ByteBuffer.wrap(data).getLong();`. –  Jul 28 '17 at 09:29
  • Or `long value = Long.parseUnsignedLong(hexString.trim(), 16);`. –  Jul 28 '17 at 09:33
  • @saka1029 both return -2619032330856274424, the value I expect is 989231983928329832L – jefry jacky Jul 28 '17 at 09:38
  • It appears your byte[] has a value that is to large to be represented in a long. Why is "989231983928329832L" the expected value? – matt Jul 28 '17 at 09:51
  • @matt 989231983928329832 convert back to byte[] data is {(byte) 0xDB, (byte) 0xA7, 0x53, (byte) 0xF8, (byte) 0xA8, 0x0C, 0x66, 0x8} – jefry jacky Jul 28 '17 at 09:54
  • 2
    How did you get that array? – matt Jul 28 '17 at 09:57
  • 1
    It looks like your conversion to `byte[]` is wrong. – matt Jul 28 '17 at 09:59

2 Answers2

1

Your byte array is incorrect.

    byte[] data = new byte[]{(byte) 0xDB, (byte) 0xA7, 0x53, (byte) 0xF8, (byte) 0xA8, 0x0C, 0x66, 0x8};
    long a = 989231983928329832L;
    byte[] bytes = ByteBuffer.allocate(8).putLong(a).array();
    for(int i = 0; i<8; i++){
        System.out.printf("%02x\t%02x\n", data[i], bytes[i]);
    }
    System.out.println(Long.parseLong(hexStringFromHexData(bytes), 16));

Which outputs.

db 0d

a7 ba

53 75

f8 3f

a8 8a

0c 80

66 c6

08 68

989231983928329832

The first column is your byte array, the second column is the one created. You can also see your string technique works with the correct byte array.

Community
  • 1
  • 1
matt
  • 10,892
  • 3
  • 22
  • 34
0

The problem you are facing is due to the face that the long type in Java is signed, so the maximum absolute value you can have is indeed 0x7fffffffffffffff, smaller that the desired 0xDBA753F8A80C6608.

You can solve the issue in several ways:

  • using BigInteger: BigInteger longValue = new BigInteger(1, data);

  • if you can work with Java 8, you can use unsigned long, as pointed out in comments from @saka1029: long value = Long.parseUnsignedLong(hexString.trim(), 16);

EDIT: after some research, I warn you that the output of the second method will appear negative if printed. This is due to the fact that the long variable is still signed, and only some methods of the Long class treat is as unsigned. Here is the source I used

bracco23
  • 2,181
  • 10
  • 28
  • The hexstring 0xDBA753F8A80C6608 is exceed Long.MAX_VALUE, for 989231983928329832L the hex string is 0xDBA753F8A80C668, so the problem is my hex string is not correct. – jefry jacky Jul 28 '17 at 10:02
  • [According to the doc](https://docs.oracle.com/javase/7/docs/api/java/lang/Long.html#MAX_VALUE), `Long.MAX_VALUE`, is 2^63-1, which is 9223372036854775807L – bracco23 Jul 28 '17 at 10:06