2011-01-22 40 views
21

Tôi có một số byte[] mà tôi đã đọc từ một tệp và tôi muốn nhận được một số int từ hai byte trong đó. Dưới đây là một ví dụ:Đọc hai byte thành một số nguyên?

byte[] bytes = new byte[] {(byte)0x00, (byte)0x2F, (byte)0x01, (byte)0x10, (byte)0x6F}; 
int value = bytes.getInt(2,4); //This method doesn't exist 

này nên value bằng 0x0110, hoặc 272 trong hệ thập phân. Nhưng rõ ràng, byte[].getInt() không tồn tại. Làm thế nào tôi có thể hoàn thành nhiệm vụ này?

Mảng trên chỉ là một ví dụ. Các giá trị thực tế không được tôi biết.

+0

lý do câu trả lời hoạt động là các byte được thăng cấp thành số nguyên trong trường hợp đó là nguyên nhân khiến bạn khó hiểu. "bytes [2] * 256" không vừa với byte, nhưng nó không phải là vấn đề vì "256" là số nguyên, v.v. – SyntaxT3rr0r

+1

có thể trùng lặp của [Chuyển đổi 4 byte thành int] (http://stackoverflow.com/questions/2383265/convert-4-bytes-to-int) – finnw

Trả lời

36

Bạn chỉ nên lựa chọn cho sự đơn giản:

int val = ((bytes[2] & 0xff) << 8) | (bytes[3] & 0xff); 

Bạn thậm chí có thể viết hàm helper của riêng bạn getBytesAsWord (byte[] bytes, int start) để cung cấp cho bạn các chức năng nếu bạn không muốn tính toán peppering mã của bạn nhưng tôi nghĩ rằng có lẽ sẽ quá mức.

+1

Lý tưởng nhất là (b1 << 8) | (b2 & 0x00ff) Nếu giá trị byte thứ hai lớn hơn 128, chuyển đổi trên cho giá trị không đúng, vì java coi byte là int âm. – Gopi

+0

Tại sao '0xff'? Nói cách khác, sự khác biệt với 'byte [0] << 8 | byte [1] '? – arve0

+1

@ arve0 xem http://stackoverflow.com/a/11380077/1685098 –

1

Ngoài ra, bạn có thể sử dụng:

int val = (bytes[2] << 8) + bytes[3] 
+1

Không: nó sẽ trả về một số âm nếu byte [2] lớn hơn 0x7f. "& 0xff" từ câu trả lời của paxdiablo là bắt buộc. – Francois

6

Hãy thử:

public static int getInt(byte[] arr, int off) { 
    return arr[off]<<8 &0xFF00 | arr[off+1]&0xFF; 
} // end of getInt 

Câu hỏi của bạn không chỉ ra những gì mà hai args (2,4) có nghĩa. 2 và 4 không có ý nghĩa trong ví dụ của bạn như là chỉ số trong mảng để tìm ox01 và 0x10, tôi đoán bạn muốn lấy hai phần tử liên tiếp, một điều phổ biến để làm, vì vậy tôi đã sử dụng tắt và 1 trong phương pháp của tôi.

Bạn không thể mở rộng lớp byte [] trong java, vì vậy bạn không thể có phương thức bytes.getInt, vì vậy tôi đã tạo một phương thức tĩnh sử dụng byte [] làm arg đầu tiên.

'lừa' với phương pháp là byte của bạn là 8 bit đã ký số nguyên và giá trị trên 0x80 là số âm và sẽ được ký mở rộng (tức là 0xFFFFFF80 khi được sử dụng làm int). Đó là lý do tại sao cần phải đeo mặt nạ '& 0xFF'. '< < 8' dịch các byte 8 bit quan trọng hơn sang trái. '|' kết hợp hai giá trị - giống như '+'. Thứ tự của các toán tử là quan trọng vì < < có quyền ưu tiên cao nhất, tiếp theo là & theo sau | - do đó không cần dấu ngoặc đơn.

+0

Thx cho lời giải thích tốt đẹp này. Đối với cùng một điều nhưng giá trị đã ký, tôi đã sử dụng: 'return arr [off] << 8 | arr [off + 1] &0xFF; ' –

0

Bạn có thể sử dụng ByteBuffer. Nó có phương thức getInt mà bạn đang tìm kiếm và nhiều phương pháp hữu ích khác

2

Đây là một cách đáng tin cậy đơn giản.

ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4); 
    // by choosing big endian, high order bytes must be put 
    // to the buffer before low order bytes 
    byteBuffer.order(ByteOrder.BIG_ENDIAN); 
    // since ints are 4 bytes (32 bit), you need to put all 4, so put 0 
    // for the high order bytes 
    byteBuffer.put((byte)0x00); 
    byteBuffer.put((byte)0x00); 
    byteBuffer.put((byte)0x01); 
    byteBuffer.put((byte)0x10); 
    byteBuffer.flip(); 
    int result = byteBuffer.getInt(); 
0

Lớp Google Base16 là từ Guava-14.0.1.

new BigInteger(com.google.common.io.BaseEncoding.base16().encode(bytesParam),16).longValue(); 
Các vấn đề liên quan