Як перетворити байтовий масив у числове значення (Java)?


89

У мене є 8-байтовий масив, і я хочу перетворити його на відповідне числове значення.

напр

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

// CONVERSION OPERATION
// return the numeric value

Я хочу метод, який буде виконувати вищевказану операцію перетворення.


4
Що ви маєте на увазі під "числовим значенням"? Чи представляють байти ціле (довге) чи число з плаваючою точкою (подвійне) у двійковому вигляді? Чи є вони рядковим поданням числа? Або ще одне представництво?
— starblue

1
Це було корисно: stackoverflow.com/questions/5399798 / ...
— TacB0sS

Примітка: Посилання TacB0sS було тим, що я насправді шукав - як перехід вперед, так і назад.
— Jay Taylor

new BigInteger(by).longValue()
— Маркіз

Відповіді:


106

Припускаючи, що перший байт є найменш значущим байтом:

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

Чи є перший байт найбільш значущим, тоді він дещо інший:

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

Замінюйте long на BigInteger , якщо у вас більше 8 байт.

Дякую Аарону Дігуллі за виправлення моїх помилок.


8
-1 байт - це підписані значення! І замініть pow () на shift (<<)! "value = (value << 8) + (by [i] & 0xff)"
— Аарон Дігулла

Чи має оператор зміни (<<) праворуч наліво пріоритету? Як працює код вище? Це все працює добре для мене. Просто хочу знати, що працює. Подяка заздалегідь
— сурадж

@Mnementh: Чи має оператор зміни (<<) праворуч наліво пріоритету? Як працює код вище? Це все працює добре для мене. Просто хочу знати, що працює. Подяка заздалегідь
— сурадж

5
У випадку, якщо хтось інший має таку ж проблему, як і я, у першому прикладі, [i] повинен бути приведений до long, інакше це працює лише для значень менше 2 ^ 32. Тобто,value += ((long)by[i] & 0xffL) << (8 * i);
— Лука

115

Для перетворення можна використовувати Buffers, які надаються як частина java.nioпакету.

Тут вихідний byte[]масив має довжину 8, тобто розмір, що відповідає longзначенню.

Спочатку byte[]масив загортається в a ByteBuffer, а потім ByteBuffer.getLongвикликається метод для отримання longзначення:

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

System.out.println(l);

Результат

4

Я хотів би подякувати dfa за вказівку на ByteBuffer.getLongметод у коментарях.


Незважаючи на те, що це може бути не застосовним у цій ситуації, краса Buffers полягає у перегляді масиву з кількома значеннями.

Наприклад, якщо у нас був 8-байтовий масив, і ми хотіли розглянути його як два intзначення, ми могли б обернути byte[]масив в an ByteBuffer, який розглядається як a, IntBufferі отримати значення за допомогою 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);

Результат:

1
4

а як щодо ByteBuffer.wrap (новий байт [] {0, 0, 0, 1, 0, 0, 0, 4}). getLong ()? цей метод повинен прочитати наступні 8 байтів і перетворити їх на довгий
— dfa

@dfa: Дякую, що вказав на це, мабуть, це працює - я відредагую відповідь. :)
— coobird

16

Якщо це 8-байтове числове значення, ви можете спробувати:

BigInteger n = new BigInteger(byteArray);

Якщо це буфер символів UTF-8, ви можете спробувати:

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

Я б проголосував за цю відповідь, якби вона закінчилася відразу після першого фрагмента коду або якщо б вона включала якийсь код для перетворення рядка у "числове значення". Як є, друга половина Вашої відповіді здається не послідовною.
— Лоуренс Гонсалвес,

Не те, що я мав на увазі спочатку, я змінив свою відповідь
— Вінсент Роберт

15

Просто, ви можете скористатися або звернутися до guava lib, наданим Google, який пропонує утилісні методи для перетворення між довгим та байтовим масивом. Код мого клієнта:

    long content = 212000607777l;
    byte[] numberByte = Longs.toByteArray(content);
    logger.info(Longs.fromByteArray(numberByte));


9

Ви також можете використовувати BigInteger для байтів змінної довжини. Ви можете перетворити його в Long, Integer або Short, залежно від ваших потреб.

new BigInteger(bytes).intValue();

або для позначення полярності:

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


1

Кожна комірка масиву обробляється як беззнакова int:

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;
}

Тільки примітка, що мені потрібно було використовувати 0xFFL, інакше для приведення з int 0xFF до long було встановлено цілу кількість неправильних 1 біт, коли я друкував Long.toHexString (l).
— Лука

Вам потрібно використовувати 0xFFL, інакше ви отримаєте розширення знака.
— Сірий
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.