I am trying to make a method to use bit shifting to convert bytes to their hex (as a char) equivalent. However, I am experiencing some unexpected results: some of the numbers come back as negative. I understand that Java does not have the equivalent of unsigned integers, and I am at a loss as to how to make this work. Here 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)]);
}
}
Here is the output:
Run: 0 First nibble: 5 Second nibble: 8 Run: 1 First nibble: 6 Second nibble: D Run: 2
Followed by: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -8 at Test.main(Test.java:10)
I know I can use String.format() to accomplish this, but I am not using that method because I need a method that works quickly while generating minimal garbage. My question for the experts is... what can I change to make this work?
UPDATE
I made the changes suggested by Ted Hopp, and it worked perfectly in the test method. I moved it over to my Android app, which converts the bytes to a MAC address into a char[] containing a formatted MAC. I'm no longer getting negative numbers, but I am getting what appear to be random miscalculations. Here is the method I am 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 a byte[] array of bytes of a packet, parser_skip is an int containing an offset where the byte is located, and hex_sb is a StringBuilder. The output from StringBuilder.toString() should be the same as String.valueOf(parser_mac)... but it isn't. Here is an example:
I/PARSER (10860): StringBuilder.getString() = AC:22:0B:40:70:41 | parser_mac = 0B:22:0A:40:70:41
I/PARSER (10860): StringBuilder.getString() = C8:F7:33:0E:7E:AF | parser_mac = B8:E7:33:0D:7D:0E
I/PARSER (10860): StringBuilder.getString() = 58:6D:8F:BA:F5:81 | parser_mac = 58:6C:8E:A0:E5:81
I/PARSER (10860): StringBuilder.getString() = AC:22:0B:40:70:41 | parser_mac = 0B:22:0A:40:70:41
My next question is... why don't they match? Thanks for any ideas that you may have.