2012-05-29 32 views
7

Tôi phải chuyển đổi byte thành ký/không dấu int hoặc ngắn.Chuyển đổi từ 2 hoặc 4 byte thành chữ ký/unsigned ngắn/int

Các phương pháp dưới đây là chính xác? Cái nào được ký và cái nào chưa được ký?

trật tự Byte: LITTLE_ENDIAN

public static int convertTwoBytesToInt1(byte b1, byte b2) { 
    return (int) ((b2 << 8) | (b1 & 0xFF)); 
} 

VS.

public static int convertTwoBytesToInt2(byte b1, byte b2) { 
    return (int) (((b2 & 0xFF) << 8) | (b1 & 0xFF)); 
} 

public static int convertFourBytesToInt1(byte b1, byte b2, byte b3, byte b4){ 
    return (int) ((b4<<24)+(b3<<16)+(b2<<8)+b1); 
} 

VS.

public static int convertFourBytesToInt2(byte b1, byte b2, byte b3, byte b4){ 
    return (int) (((b4 & 0xFF) << 24) | ((b3 & 0xFF) << 16) | ((b2 & 0xFF) << 8) | (b1 & 0xFF)); 
} 

Tôi quan tâm chỉ trong các hình thức chuyển đổi này. Cảm ơn!

+1

Tôi sẽ sử dụng ByteBuffer vì điều này có thể hiệu quả hơn và bạn chỉ có thể thiết lập '.order (ByteOrder.LITTLE_ENDIAN) ' –

Trả lời

6

Phương thức đầu tiên (convertXXXToInt1()) của mỗi cặp được ký, thứ hai (convertXXXToInt2()) chưa được ký.

Tuy nhiên, Java int luôn được ký, vì vậy nếu bit cao nhất là b4 được đặt, kết quả của convertFourBytesToInt2() sẽ là số âm, mặc dù đây được cho là phiên bản "chưa ký".

Giả sử giá trị byte, b2 bằng -1 hoặc 0xFF trong hệ thập lục phân. Toán tử << sẽ khiến nó được "thăng cấp" thành loại int với giá trị -1 hoặc 0xFFFFFFFF. Sau khi thay đổi 8 bit, nó sẽ là 0xFFFFFF00, và sau một sự thay đổi 24 byte, nó sẽ là 0xFF000000.

Tuy nhiên, nếu bạn áp dụng toán tử bitwise &, các bit bậc cao hơn sẽ được đặt thành 0. Điều này loại bỏ các thông tin đăng nhập. Dưới đây là các bước đầu tiên của hai trường hợp, làm việc chi tiết hơn.

Signed:

byte b2 = -1; // 0xFF 
int i2 = b2; // 0xFFFFFFFF 
int n = i2 << 8; // 0x0xFFFFFF00 

Unsigned:

byte b2 = -1; // 0xFF 
int i2 = b2 & 0xFF; // 0x000000FF 
int n = i2 << 8; // 0x0000FF00 
+0

Tại convertFourBytesToInt1 b1 không có & 0xff ... Vì vậy, nếu tôi không đặt Nó không có Gì Thay đổi? Vẫn đang ký int? – blackwolf

+0

@blackwolf Trên thực tế, nó sẽ tạo ra sự khác biệt, bởi vì bạn đang kết hợp các byte với toán tử '+'. Tôi đã không nhận thấy rằng trước đây, bởi vì những người khác sử dụng toán tử '|', được ưu tiên cho thao tác bit. Biểu thức phải là '(int) ((b4 << 24) | ((b3 & 0xFF) << 16) | ((b2 & 0xFF) << 8) | (b1 & 0xFF))' – erickson

1

Có một vấn đề với 4-byte unsigned chuyển đổi, bởi vì nó không phù hợp với một int. Các thói quen dưới đây hoạt động chính xác.

public class IntegerConversion 
{ 
    public static int convertTwoBytesToInt1 (byte b1, byte b2)  // signed 
    { 
    return (b2 << 8) | (b1 & 0xFF); 
    } 

    public static int convertFourBytesToInt1 (byte b1, byte b2, byte b3, byte b4) 
    { 
    return (b4 << 24) | (b3 & 0xFF) << 16 | (b2 & 0xFF) << 8 | (b1 & 0xFF); 
    } 

    public static int convertTwoBytesToInt2 (byte b1, byte b2)  // unsigned 
    { 
    return (b2 & 0xFF) << 8 | (b1 & 0xFF); 
    } 

    public static long convertFourBytesToInt2 (byte b1, byte b2, byte b3, byte b4) 
    { 
    return (long) (b4 & 0xFF) << 24 | (b3 & 0xFF) << 16 | (b2 & 0xFF) << 8 | (b1 & 0xFF); 
    } 

    public static void main (String[] args) 
    { 
    byte b1 = (byte) 0xFF; 
    byte b2 = (byte) 0xFF; 
    byte b3 = (byte) 0xFF; 
    byte b4 = (byte) 0xFF; 

    System.out.printf ("%,14d%n", convertTwoBytesToInt1 (b1, b2)); 
    System.out.printf ("%,14d%n", convertTwoBytesToInt2 (b1, b2)); 

    System.out.printf ("%,14d%n", convertFourBytesToInt1 (b1, b2, b3, b4)); 
    System.out.printf ("%,14d%n", convertFourBytesToInt2 (b1, b2, b3, b4)); 
    } 
} 
+0

b1 là gì & 0xFF cho? – ScottF

+0

@ScottF - để ngăn chặn các giá trị âm. – dmolony

Các vấn đề liên quan