Как преобразовать массив байтов в его числовое значение (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 03
NB: Ссылка TacB0sS была тем, что я действительно искал - как прямое, так и обратное преобразование.
Джей Тейлор
new BigInteger(by).longValue()
Marquis of Lorne

Ответы:

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 байт.

Спасибо Аарону Дигулле за исправление моих ошибок.

Mnementh
источник
8
-1 байт - это значения со знаком! И замените pow () на shift (<<)! "value = (value << 8) + (by [i] & 0xff)"
Аарон Дигулла,
Имеет ли оператор сдвига (<<) приоритет справа налево? Как работает вышеуказанный код? У меня все работает нормально. Просто хочу знать, как работает. Заранее
спасибо
@Mnementh: имеет ли оператор сдвига (<<) приоритет справа налево? Как работает вышеуказанный код? У меня все работает нормально. Просто хочу знать, как работает. Спасибо заранее
сурадж
5
Если у кого-то еще есть такая же проблема, как и у меня, в первом примере by [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[]массив в 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
Coobird
источник
как насчет ByteBuffer.wrap (new byte [] {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

Каждая ячейка в массиве обрабатывается как unsigned 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, иначе вы получите расширение знака.
Грей