Преобразовать массив байтов в целое число на 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;