Преобразовать массив байтов в целое число на Java и наоборот
Я хочу хранить некоторые данные в массивах байтов в Java. В основном просто цифры, которые могут принимать до 2 байтов на номер.
Я хотел бы знать, как я могу преобразовать целое число в массив длиной 2 байта и наоборот. Я нашел много решений googling, но большинство из них не объясняют, что происходит в коде. Там много смещающих вещей, которые я действительно не понимаю, поэтому я хотел бы получить базовое объяснение.
Ответы
Ответ 1
Используйте классы, найденные в пространстве имен java.nio
, в частности, ByteBuffer
. Он может выполнять всю работу за вас.
byte[] arr = { 0x00, 0x01 };
ByteBuffer wrapped = ByteBuffer.wrap(arr); // big-endian by default
short num = wrapped.getShort(); // 1
ByteBuffer dbuf = ByteBuffer.allocate(2);
dbuf.putShort(num);
byte[] bytes = dbuf.array(); // { 0, 1 }
Ответ 2
byte[] toByteArray(int value) {
return ByteBuffer.allocate(4).putInt(value).array();
}
byte[] toByteArray(int value) {
return new byte[] {
(byte)(value >> 24),
(byte)(value >> 16),
(byte)(value >> 8),
(byte)value };
}
int fromByteArray(byte[] bytes) {
return ByteBuffer.wrap(bytes).getInt();
}
// packing an array of 4 bytes to an int, big endian, minimal parentheses
// operator precedence: <<, &, |
// when operators of equal precedence (here bitwise OR) appear in the same expression, they are evaluated from left to right
int fromByteArray(byte[] bytes) {
return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}
// packing an array of 4 bytes to an int, big endian, clean code
int fromByteArray(byte[] bytes) {
return ((bytes[0] & 0xFF) << 24) |
((bytes[1] & 0xFF) << 16) |
((bytes[2] & 0xFF) << 8 ) |
((bytes[3] & 0xFF) << 0 );
}
При упаковке подписанных байтов в int каждый байт должен быть замаскирован, потому что он расширен до 32 бит (а не до нуля) из-за правила арифметического продвижения (описанного в JLS, Conversions and Promotions).
Есть интересная головоломка, связанная с этим, описанная в Java Puzzlers ("Большое наслаждение каждым байтом") Джошуа Блоха и Нила Гафтера. При сравнении значения байта со значением типа int байт расширяется до значения типа int, а затем это значение сравнивается с другим значением типа int.
byte[] bytes = (…)
if (bytes[0] == 0xFF) {
// dead code, bytes[0] is in the range [-128,127] and thus never equal to 255
}
Обратите внимание, что все числовые типы подписаны в Java, за исключением того, что char является 16-разрядным целочисленным типом без знака.
Ответ 3
Вы также можете использовать BigInteger для байтов переменной длины. Вы можете преобразовать его в long, int или short, в зависимости от ваших потребностей.
new BigInteger(bytes).intValue();
или обозначить полярность:
new BigInteger(1, bytes).intValue();
Чтобы просто вернуть байты:
new BigInteger(bytes).toByteArray()
Ответ 4
Базовая реализация будет выглядеть примерно так:
public class Test {
public static void main(String[] args) {
int[] input = new int[] { 0x1234, 0x5678, 0x9abc };
byte[] output = new byte[input.length * 2];
for (int i = 0, j = 0; i < input.length; i++, j+=2) {
output[j] = (byte)(input[i] & 0xff);
output[j+1] = (byte)((input[i] >> 8) & 0xff);
}
for (int i = 0; i < output.length; i++)
System.out.format("%02x\n",output[i]);
}
}
Чтобы понять вещи, вы можете прочитать эту статью WP: http://en.wikipedia.org/wiki/Endianness
Приведенный выше исходный код выведет 34 12 78 56 bc 9a
. Первые 2 байта (34 12
) представляют первое целое число и т.д. Приведенный выше исходный код кодирует целые числа в формате с прямым порядком байтов.
Ответ 5
/** length should be less than 4 (for int) **/
public long byteToInt(byte[] bytes, int length) {
int val = 0;
if(length>4) throw new RuntimeException("Too big to fit in int");
for (int i = 0; i < length; i++) {
val=val<<8;
val=val|(bytes[i] & 0xFF);
}
return val;
}
Ответ 6
Кто-то, у кого есть требование, когда они должны читать из битов, скажет, что вам нужно читать только 3 бита, но вам нужно целое число со знаком, а затем использовать следующее:
data is of type: java.util.BitSet
new BigInteger(data.toByteArray).intValue() << 32 - 3 >> 32 - 3
Магическое число 3
может быть заменено на количество бит (не байтов), которое вы используете.
Ответ 7
Я думаю, что это лучший режим, который нужно передать в int
public int ByteToint(Byte B){
String comb;
int out=0;
comb=B+"";
salida= Integer.parseInt(comb);
out=out+128;
return out;
}
первый обходный байт в String
comb=B+"";
Следующий шаг заключается в int
out= Integer.parseInt(comb);
но байт находится в ярости от -128 до 127 для этого reasone, я думаю, лучше использовать rage от 0 до 255, и вам нужно только это сделать:
out=out+256;