Qaiser Mehmood
Qaiser Mehmood

Reputation: 975

why Java throws a NumberFormatException

I got an exception while parsing a string to byte

String Str ="9B7D2C34A366BF890C730641E6CECF6F";

String [] st=Str.split("(?<=\\G.{2})");

byte[]bytes = new byte[st.length];
for (int i = 0; i <st.length; i++) {
 bytes[i] = Byte.parseByte(st[i]);
}

Upvotes: 2

Views: 8332

Answers (3)

Chrissi
Chrissi

Reputation: 1218

Java is very picky on signedness, it will not accept values to overflow. Thus, if you parse a Byte and it is larger than 127 (for example, 130 dec or 83 hex) you will get a NumberFormatException. Same happens if you parse an 8 digit hex number as an Integer (or a 16 digit hex number as a Long) and it starts with 8-F. Such values will not be interpreted as negative (two's complement) but as illegal.

If you think that this is anal retentive, I totally agree. But that's Java style.

To parse hex values as two's complement numbers either use a large enough integer type (for example, if you are parsing a Byte use Integer instead and type cast it to a byte later) or -- if you need to parse a Long, split the number in half it is 16 digits, then combine. Here's an example:

public static long longFromHex(String s) throws IllegalArgumentException {
    if (s.length() == 16)
        return (Long.parseLong(s.substring(0,8),16)<<32)|(Long.parseLong(s.substring(8,16),16)&0xffffffffL);
    return Long.parseLong(s, 16);
}

Or, to read a Byte, just use Integer instead:

public static byte byteFromHex(String s) throws IllegalArgumentException {
    int i = Integer.parseInt(s, 16);
    if (i < 0 || i > 255) throw new IllegalArgumentException("input string "+s+" does not fit into a Byte");
    return (byte)i;
}

Upvotes: 1

MByD
MByD

Reputation: 137442

That's because the default parse method expects a number in decimal format, to parse hexadecimal number, use this parse:

Byte.parseByte(st[i], 16);

Where 16 is the base for the parsing.

As for your comment, you are right. The maximum value of Byte is 0x7F. So you can parse it as int and perform binary AND operation with 0xff to get the LSB, which is your byte:

bytes[i] = Integer.parseInt(st[i], 16) & 0xFF;

Upvotes: 5

Paŭlo Ebermann
Paŭlo Ebermann

Reputation: 74800

Assuming you want to parse the string as hexadecimal, try this:

bytes[i] = Byte.parseByte(st[i], 16);

The default radix is 10, and obviously B is not a base-10-digit.

Upvotes: 5

Related Questions