Làm thế nào để chuyển đổi một mảng byte thành giá trị số của nó (Java)?


89

Tôi có một mảng 8 byte và tôi muốn chuyển đổi nó thành giá trị số tương ứng.

ví dụ

byte[] by = new byte[8];  // the byte array is stored in 'by'

// CONVERSION OPERATION
// return the numeric value

Tôi muốn một phương thức sẽ thực hiện thao tác chuyển đổi ở trên.


4
Bạn có nghĩa là gì bởi "giá trị số"? Các byte có đại diện cho số nguyên (dài) hoặc số dấu phẩy động (kép) trong hệ nhị phân không? Chúng có phải là biểu diễn chuỗi của một số không? Hay một đại diện khác?
starblue

1
Điều này rất hữu ích: stackoverflow.com/questions/5399798/…
TacB0sS

NB: Liên kết TacB0sS là những gì tôi thực sự đang tìm kiếm - cả chuyển đổi chuyển tiếp và chuyển đổi ngược.
Jay Taylor

new BigInteger(by).longValue()
Marquis of Lorne

Câu trả lời:


106

Giả sử byte đầu tiên là byte ít quan trọng nhất:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value += ((long) by[i] & 0xffL) << (8 * i);
}

Có phải byte đầu tiên là quan trọng nhất, sau đó nó hơi khác một chút:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value = (value << 8) + (by[i] & 0xff);
}

Thay thế long bằng BigInteger , nếu bạn có nhiều hơn 8 byte.

Cảm ơn Aaron Digulla đã sửa lỗi cho tôi.


8
-1 byte là giá trị có dấu! Và thay thế pow () bằng shift (<<)! "value = (giá trị << 8) + (bởi [i] & 0xff)"
Aaron Digulla

Toán tử shift (<<) có ưu tiên từ phải sang trái không? Mã trên hoạt động như thế nào? Nó hoạt động tốt cho tôi. Chỉ muốn biết công việc. Thanx trước
suraj

@Mnementh: Toán tử shift (<<) có ưu tiên từ phải sang trái không? Mã trên hoạt động như thế nào? Nó hoạt động tốt cho tôi. Chỉ muốn biết công việc. Thanx trước
suraj

5
Trong trường hợp bất kỳ ai khác gặp vấn đề tương tự như tôi đã làm, trong ví dụ đầu tiên, bởi [i] phải được chuyển thành dài, nếu không, nó chỉ hoạt động với các giá trị nhỏ hơn 2 ^ 32. Đó là,value += ((long)by[i] & 0xffL) << (8 * i);
Luke

115

Người ta có thể sử dụng các Buffers được cung cấp như một phần của java.niogói để thực hiện chuyển đổi.

Ở đây, byte[]mảng nguồn có độ dài 8, là kích thước tương ứng với một longgiá trị.

Đầu tiên, byte[]mảng được bao bọc trong a ByteBuffer, và sau đó ByteBuffer.getLongphương thức được gọi để nhận longgiá trị:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 4});
long l = bb.getLong();

System.out.println(l);

Kết quả

4

Tôi muốn cảm ơn dfa vì đã chỉ ra ByteBuffer.getLongphương pháp trong các bình luận.


Mặc dù nó có thể không áp dụng được trong tình huống này, nhưng vẻ đẹp của các Buffers đi kèm với việc xem xét một mảng có nhiều giá trị.

Ví dụ: nếu chúng ta có một mảng 8 byte và chúng ta muốn xem nó dưới dạng hai intgiá trị, chúng ta có thể bao bọc byte[]mảng trong một ByteBuffer, được xem là a IntBuffervà nhận các giá trị bằng cách IntBuffer.get:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 1, 0, 0, 0, 4});
IntBuffer ib = bb.asIntBuffer();
int i0 = ib.get(0);
int i1 = ib.get(1);

System.out.println(i0);
System.out.println(i1);

Kết quả:

1
4

Còn ByteBuffer.wrap (byte mới [] {0, 0, 0, 1, 0, 0, 0, 4}). getLong () thì sao? phương pháp này nên đọc tiếp theo 8 byte và chuyển đổi chúng sang một chặng đường dài
DFA

@dfa: Cảm ơn bạn đã chỉ ra điều đó, nó chắc chắn có hiệu quả - Tôi sẽ chỉnh sửa câu trả lời. :)
coobird

16

Nếu đây là giá trị số 8 byte, bạn có thể thử:

BigInteger n = new BigInteger(byteArray);

Nếu đây là bộ đệm ký tự UTF-8, thì bạn có thể thử:

BigInteger n = new BigInteger(new String(byteArray, "UTF-8"));

Tôi sẽ bỏ phiếu cho câu trả lời này nếu nó kết thúc ngay sau đoạn mã đầu tiên hoặc nếu nó bao gồm một số mã để chuyển đổi chuỗi thành "giá trị số". Hiện tại, nửa sau câu trả lời của bạn có vẻ như không phải là câu trả lời.
Laurence Gonsalves

Không phải những gì tôi muốn nói ở nơi đầu tiên, tôi đã thay đổi câu trả lời của tôi
Vincent Robert


9

Bạn cũng có thể sử dụng BigInteger cho các byte có độ dài thay đổi. Bạn có thể chuyển đổi nó thành Dài, Số nguyên hoặc Ngắn, tùy theo nhu cầu của bạn.

new BigInteger(bytes).intValue();

hoặc để biểu thị cực:

new BigInteger(1, bytes).intValue();


1

Mỗi ô trong mảng được coi là int không dấu:

private int unsignedIntFromByteArray(byte[] bytes) {
int res = 0;
if (bytes == null)
    return res;


for (int i=0;i<bytes.length;i++){
    res = res | ((bytes[i] & 0xff) << i*8);
}
return res;
}

Chỉ cần lưu ý rằng tôi cần sử dụng 0xFFL, nếu không quá trình truyền từ int 0xFF đến long có rất nhiều bit 1 không chính xác được đặt khi tôi in Long.toHexString (l).
Luke

Bạn cần sử dụng 0xFFL nếu không bạn sẽ nhận được phần mở rộng đăng nhập.
Màu xám
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.