Java displacement causes a negative number
I try to use displacement to convert bytes to hexadecimal (as char) equivalent However, I encountered some unexpected results: some numbers came back I know Java has no equivalent unsigned integer, and I don't know how to make this work This is my code:
final static char[] hex_val = "0123456789ABCDEF".tocharArray(); public static void main(String[] args) { byte[] bytes = {(byte) 0x58,(byte) 0x6D,(byte) 0x8F,(byte) 0xBA,(byte) 0xF5,(byte) 0x81}; for (int i = 0; i < bytes.length; i++) { System.out.println("Run: " + i); System.out.println("First nibble: " + hex_val[(bytes[i] >> 4)]); System.out.println("Second nibble: " + hex_val[(bytes[i] & 0xf)]); } }
This is the output:
The second is the exception Java in the thread "main" Lang. ArrayIndexOutOfBoundsException: - 8 in test main(Test.java:10)
I know I can use string Format () to do this, but I didn't use this method because I needed a method that worked quickly while generating the least garbage My question to experts is... What can I change to make this work successful?
UPDATE
I made the modification suggested by Ted HOPP, which works perfectly in the test method I moved it to my Android application, which converts bytes into MAC addresses to char [], which contains formatted Mac I no longer get negative numbers, but what I get seems to be a random miscalculation This is the method I'm using:
static final char[] parser_hex_arr = "01234567890ABCDEF".tocharArray(); static final char[] parser_mac = " : : : : : ".tocharArray(); void parseMac() { hex_sb.setLength(0); for (hex_counter = 0; hex_counter < 6; hex_counter++) { hex_sb.append(String.format("%02X",parser_packet_bytes[parser_skip + hex_counter])); if (!(hex_counter == 5)) { hex_sb.append(":"); } } parser_mac[0] = parser_hex_arr[ (parser_packet_bytes[parser_skip] >> 4) & 0x0f ]; parser_mac[1] = parser_hex_arr[ (parser_packet_bytes[parser_skip] & 0xf) ]; parser_mac[3] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 1] >> 4) & 0x0f ]; parser_mac[4] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 1] & 0xf) ]; parser_mac[6] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 2] >> 4) & 0x0f ]; parser_mac[7] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 2] & 0xf) ]; parser_mac[9] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 3] >> 4) & 0x0f ]; parser_mac[10] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 3] & 0xf) ]; parser_mac[12] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 4] >> 4) & 0x0f ]; parser_mac[13] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 4] & 0xf) ]; parser_mac[15] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 5] >> 4) & 0x0f ]; parser_mac[16] = parser_hex_arr[ (parser_packet_bytes[parser_skip + 5] & 0xf) ]; Log.i("PARSER","StringBuilder.getString() = " + hex_sb.toString() + " | parser_mac = " + String.valueOf(parser_mac)); formatted_mac = String.valueOf(parser_mac); }
parser_ packet_ Bytes is the byte [] byte array of the packet, parser_ Skip is an int containing the offset of the byte, and hex_ Sb is a StringBuilder StringBuilder. The output of tostring() should be the same as string Valueof (parser_mac) is the same... But this is not the case Here is an example:
My next question is... Why don't they match? Thank you for any ideas
Solution
This is due to the delay of signature Byte values are signed in Java, so any value greater than 0x7F is considered negative The displacement operator converts two operands to integers before performing a shift You need to mask the bottom byte after integer promotion For example:
((bytes[i] & 0xff) >> 4)
or
((bytes[i] >> 4) & 0x0f)
replace
(bytes[i] >> 4)