[英]Java bit-shift results in negative number
我試圖使用位移來將字節轉換為十六進制(作為char)等效的方法。 但是,我遇到了一些意想不到的結果:一些數字又回來了。 我知道Java沒有等效的無符號整數,我不知道如何使這個工作。 這是我的代碼:
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)]);
}
}
這是輸出:
運行:0首先半字節:5秒半字節:8運行:1首先半字節:6秒半字節:D運行:2
接下來是:線程“main”中的異常java.lang.ArrayIndexOutOfBoundsException:-8 at Test.main(Test.java:10)
我知道我可以使用String.format()來實現這一點,但我沒有使用該方法,因為我需要一個在生成最少垃圾的同時快速工作的方法。 我對專家的問題是......我可以改變什么使這項工作成功?
UPDATE
我做了Ted Hopp建議的修改,它在測試方法中完美運行。 我將它移動到我的Android應用程序,該應用程序將字節轉換為MAC地址為包含格式化MAC的char []。 我不再得到負數,但我得到的似乎是隨機誤算。 這是我正在使用的方法:
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是數據包的byte []字節數組,parser_skip是一個包含字節所在的偏移量的int,而hex_sb是一個StringBuilder。 StringBuilder.toString()的輸出應該與String.valueOf(parser_mac)相同......但事實並非如此。 這是一個例子:
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
我的下一個問題是......他們為什么不匹配? 感謝您的任何想法。
這是由於簽名延期。 字節值在Java中簽名,因此超過0x7f的任何值都被視為負值。 位移操作符在執行移位之前將兩個操作數轉換為整數。 您需要在整數提升后屏蔽底部字節。 例如:
((bytes[i] & 0xff) >> 4)
要么
((bytes[i] >> 4) & 0x0f)
代替
(bytes[i] >> 4)
當將字節擴展為整數時,java將進行位擴展,因此您需要屏蔽高位。
System.out.println("First nibble: " + hex_val[(bytes[i] >> 4) & 0x0f]);
System.out.println("Second nibble: " + hex_val[(bytes[i] & 0x0f)]);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.