在網絡協議解析、二進制文件處理、加密算法等場景中,byte 與二進制/十進制字符串的高效互轉是基礎技能。本文揭示有符號 byte 的補碼陷阱,提供生產級工具方法。
-128 ~ 127byte b = -1 其二進制為 11111111(而非 -0000001)Integer.toBinaryString(b) 會符號擴展為 32 位 11111111111111111111111111111111public final class ByteConvertUtils {
/** byte → 8 位二進制字符串(補碼形式) */
public static String toBinaryString(byte b) {
// 關鍵:& 0xFF 將 byte 以無符號方式提升為 int,避免符號擴展
return String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0');
}
/** 二進制字符串 → 十進制 int */
public static int binaryToInt(String binary) {
return Integer.parseInt(binary, 2);
}
/** byte → 無符號十進制 int (0-255) */
public static int toUnsignedInt(byte b) {
return b & 0xFF;
}
/** 有符號 byte → 十進制字符串 (-128~127) */
public static String toSignedString(byte b) {
return String.valueOf(b);
}
/** 十進制字符串 → byte(自動檢測範圍) */
public static byte parseByte(String decimal) {
int val = Integer.parseInt(decimal);
if (val < -128 || val > 255) {
throw new IllegalArgumentException("超出 byte 範圍: " + val);
}
return (byte) val; // 255 會正確轉為 -1
}
/** byte[] → 十六進制字符串(常用於日誌/調試) */
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
sb.append(String.format("%02X", b & 0xFF));
}
return sb.toString();
}
}
public class ByteConvertTest {
public static void main(String[] args) {
byte b = -1; // 0xFF
System.out.println("byte 值: " + b);
System.out.println("二進制: " + ByteConvertUtils.toBinaryString(b)); // 11111111
System.out.println("無符號十進制: " + ByteConvertUtils.toUnsignedInt(b)); // 255
System.out.println("有符號十進制: " + ByteConvertUtils.toSignedString(b)); // -1
String bin = "11111111";
System.out.println("二進制 " + bin + " → 十進制: " + ByteConvertUtils.binaryToInt(bin)); // 255
byte[] data = {0x01, 0x23, (byte)0xAB, (byte)0xCD};
System.out.println("字節數組 → Hex: " + ByteConvertUtils.bytesToHex(data)); // 0123ABCD
}
}
// int → 4 字節大端序
public static byte[] intToBytesBigEndian(int val) {
return new byte[] {
(byte) (val >>> 24), (byte) (val >>> 16),
(byte) (val >>> 8), (byte) val
};
}
// 4 字節大端序 → int
public static int bytesToIntBigEndian(byte[] bytes, int offset) {
return ((bytes[offset] & 0xFF) << 24) |
((bytes[offset+1] & 0xFF) << 16) |
((bytes[offset+2] & 0xFF) << 8) |
(bytes[offset+3] & 0xFF);
}
推薦: 生產環境優先使用 ByteBuffer 或 Netty ByteBuf,自動處理端序與擴容:
ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN);
buffer.putInt(0x0123ABCD);
byte[] arr = buffer.array(); // [0x01, 0x23, 0xAB, 0xCD]
| 錯誤寫法 | 後果 | 正確寫法 |
|---|---|---|
Integer.toBinaryString(byteVal) | 符號擴展產生 32 位字符串 | Integer.toBinaryString(byteVal & 0xFF) |
String.format("%08d", byteVal) | 格式化十進制而非二進制 | String.format("%8s", ...).replace(' ', '0') |
忽略 0xFF 掩碼 | 負數轉無符號結果錯誤 | 所有 byte→int 提升必加 & 0xFF |
| 手寫移位解析多字節 | 易出端序錯誤、越界 | 使用 ByteBuffer/DataInputStream |
byte & 0xFF是 Java 位運算的黃金法則:將有符號 byte 以無符號語義提升為 int,消除補碼陷阱。掌握這一核心模式,所有二進制轉換問題迎刃而解。