Як перетворити байтовий масив у числове значення (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.