Java целочисленный в байтовый массив

191

Я получил целое число: 1695609641

когда я использую метод:

String hex = Integer.toHexString(1695609641);
system.out.println(hex); 

дает:

6510f329

но я хочу байтовый массив:

byte[] bytearray = new byte[] { (byte) 0x65, (byte)0x10, (byte)0xf3, (byte)0x29};

Как я могу сделать это?

Штефана
источник

Ответы:

294

использовать Java NIO ByteBuffer очень просто:

byte[] bytes = ByteBuffer.allocate(4).putInt(1695609641).array();

for (byte b : bytes) {
   System.out.format("0x%x ", b);
}

вывод:

0x65 0x10 0xf3 0x29 
DFA
источник
4
Или используйте формат, "0x%02X"если вам всегда нужны два шестнадцатеричных символа, а также шестнадцатеричные символы в верхнем регистре, например, System.out.format("0x%02X", (byte) 10)дисплеи 0x0A.
Maarten Bodewes
12
Вы можете использовать Integer.SIZE / 8, чтобы избежать жесткого кодирования 4, который хорошо подходит для других типов, таких как Long.
davenpcj
3
@davenpcj Вы даже можете использовать Integer.SIZE / Byte.SIZE
rkosegi
11
@rkosegi Или даже Integer.BYTES начиная с Java 8 :)
drvdijk
1
В ветке @MaartenBodewes нет ничего для видимого форматирования, кроме операции с собственным типом
Jacek Cz
147

Как насчет:

public static final byte[] intToByteArray(int value) {
    return new byte[] {
            (byte)(value >>> 24),
            (byte)(value >>> 16),
            (byte)(value >>> 8),
            (byte)value};
}

Идея не моя . Я взял это из некоторого поста на dzone.com .

Гжегож Оледзки
источник
44
Я понимаю вашу точку зрения, но для этой конкретной задачи «мой» код является более декларативным и понятным, чем какой-то «волшебный» ByteBuffer, который нужно проверить, чтобы увидеть, что он делает.
Гжегож Оледзки
24
@Kevin - это очень резко - есть много случаев, когда такой код подходит, например, при обработке изображений. Библиотеки JDK в целом хороши, но они не охватывают и / или не оптимизированы для всех случаев использования.
Микера
14
согласовано; издержки и сложность ByteBuffer могут не подходить по сравнению с некоторыми простыми и хорошо известными байтовыми операциями.
swdunlop
6
Еще один момент, который я хотел бы добавить, это то, что вы использовали оператор без смещения вправо, >>>а не оператор смещения вправо >>( docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html ), поэтому поведение может быть не таким, как хотелось бы / как и ожидалось, со
знаком
4
Этот подход кажется немного быстрее, чем упомянутые методы ByteBuffer или BigInteger. Что-то еще нужно учитывать, если вы будете делать много конверсий.
ищущий
45

BigInteger.valueOf(1695609641).toByteArray()

vmpn
источник
2
какая у вас гарантия, что это даст 4-байтовый массив?
MeBigFatGuy
2
Именно то, что написал MeBigFatGuy. Javadoc о BigInteger.toByteArray()состоянии: «Массив будет содержать минимальное количество байтов, необходимое для представления этого BigInteger ...»
icza
2
Где в вопросе запрашивается байтовый массив фиксированной длины 4? В зависимости от алгоритма, это должно быть частью вас, вы можете использовать длину массива
vmpn
это намного более динамично и должно быть правильным ответом. Вы можете просто добавить массив, чтобы создать желаемый размер, если хотите. Особенно, когда вам нужно учитывать значения int со знаком Java.
Droid Chris
2
Это создает один байт для 0x7f и два байта для 0x80 (два байта: 0x0 0x80).
шотландец
26
byte[] IntToByteArray( int data ) {    
    byte[] result = new byte[4];
    result[0] = (byte) ((data & 0xFF000000) >> 24);
    result[1] = (byte) ((data & 0x00FF0000) >> 16);
    result[2] = (byte) ((data & 0x0000FF00) >> 8);
    result[3] = (byte) ((data & 0x000000FF) >> 0);
    return result;        
}
Юрий Финченко
источник
22

Использование гуавы :

byte[] bytearray = Ints.toByteArray(1695609641);
Александр Дубинский
источник
7
byte[] conv = new byte[4];
conv[3] = (byte) input & 0xff;
input >>= 8;
conv[2] = (byte) input & 0xff;
input >>= 8;
conv[1] = (byte) input & 0xff;
input >>= 8;
conv[0] = (byte) input;
Карл Смотриц
источник
2
Это извлекает наименее значимые 8 байтов. Это также позволяет избежать перетаскивания знака входного числа в преобразованный октет.
Карл Смотриц
stackoverflow.com/questions/35305634/… - не могли бы вы решить эту C # в Java?
5
public static byte[] intToBytes(int x) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream out = new DataOutputStream(bos);
    out.writeInt(x);
    out.close();
    byte[] int_bytes = bos.toByteArray();
    bos.close();
    return int_bytes;
}
lyon819
источник
4

Чанки ниже работают как минимум для отправки int через UDP.

int в байтовый массив:

public byte[] intToBytes(int my_int) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutput out = new ObjectOutputStream(bos);
    out.writeInt(my_int);
    out.close();
    byte[] int_bytes = bos.toByteArray();
    bos.close();
    return int_bytes;
}

байтовый массив для int:

public int bytesToInt(byte[] int_bytes) throws IOException {
    ByteArrayInputStream bis = new ByteArrayInputStream(int_bytes);
    ObjectInputStream ois = new ObjectInputStream(bis);
    int my_int = ois.readInt();
    ois.close();
    return my_int;
}
HaoQi Li
источник
4
использование ObjectOutputStream неверно. Используйте DataOutputStream, использование OOS делает так, чтобы байтовый массив не был 4 байта.
MeBigFatGuy
2

Поскольку обычно вы захотите преобразовать этот массив обратно в int на более позднем этапе, вот методы преобразования массива int в массив байтов и наоборот:

public static byte[] convertToByteArray(final int[] pIntArray)
{
    final byte[] array = new byte[pIntArray.length * 4];
    for (int j = 0; j < pIntArray.length; j++)
    {
        final int c = pIntArray[j];
        array[j * 4] = (byte)((c & 0xFF000000) >> 24);
        array[j * 4 + 1] = (byte)((c & 0xFF0000) >> 16);
        array[j * 4 + 2] = (byte)((c & 0xFF00) >> 8);
        array[j * 4 + 3] = (byte)(c & 0xFF);
    }
    return array;
}

public static int[] convertToIntArray(final byte[] pByteArray)
{
    final int[] array = new int[pByteArray.length / 4];
    for (int i = 0; i < array.length; i++)
        array[i] = (((int)(pByteArray[i * 4]) << 24) & 0xFF000000) |
                (((int)(pByteArray[i * 4 + 1]) << 16) & 0xFF0000) |
                (((int)(pByteArray[i * 4 + 2]) << 8) & 0xFF00) |
                ((int)(pByteArray[i * 4 + 3]) & 0xFF);
    return array;
}

Обратите внимание, что из-за распространения знака и тому подобного "& 0xFF ..." необходимы при преобразовании обратно в int.

jytou
источник
1
integer & 0xFF

за первый байт

(integer >> 8) & 0xFF

для второго и цикла и т. д., запись в предварительно выделенный байтовый массив. К сожалению, немного грязно.

Брайан Агнью
источник
1

Класс org.apache.hadoop.hbase.util.Bytes имеет несколько удобных методов преобразования byte [], но вы можете не захотеть добавлять весь JBase-jar в ваш проект только для этой цели. Удивительно, что не только такой метод пропускает AFAIK из JDK, но также и от очевидных библиотек, таких как обыкновенные.

mlohbihler
источник
1

Моя попытка:

public static byte[] toBytes(final int intVal, final int... intArray) {
    if (intArray == null || (intArray.length == 0)) {
        return ByteBuffer.allocate(4).putInt(intVal).array();
    } else {
        final ByteBuffer bb = ByteBuffer.allocate(4 + (intArray.length * 4)).putInt(intVal);
        for (final int val : intArray) {
            bb.putInt(val);
        }
        return bb.array();
    }
}

С его помощью вы можете сделать это:

byte[] fourBytes = toBytes(0x01020304);
byte[] eightBytes = toBytes(0x01020304, 0x05060708);

Полный класс здесь: https://gist.github.com/superbob/6548493 , он поддерживает инициализацию от коротких или длинных

byte[] eightBytesAgain = toBytes(0x0102030405060708L);
SuperBob
источник
1

Если вы используете Apache-Commons

public static byte[] toByteArray(int value) {
    byte result[] = new byte[4];
    return Conversion.intToByteArray(value, 0, result, 0, 4);
}
Neeraj
источник