Перетворити ціле число в байтовий масив (Java)


137

який швидкий спосіб перетворити Integerв Byte Array?

напр 0xAABBCCDD => {AA, BB, CC, DD}


1
Чи має значення, у якому форматі утворюється байтовий масив? Що ти з цим зробиш?
skaffman

Відповіді:


237

Погляньте на клас ByteBuffer .

ByteBuffer b = ByteBuffer.allocate(4);
//b.order(ByteOrder.BIG_ENDIAN); // optional, the initial order of a byte buffer is always BIG_ENDIAN.
b.putInt(0xAABBCCDD);

byte[] result = b.array();

Установка забезпечує порядку байтів , що result[0] == 0xAA, result[1] == 0xBB, result[2] == 0xCCі result[3] == 0xDD.

Або ж ви можете це зробити вручну:

byte[] toBytes(int i)
{
  byte[] result = new byte[4];

  result[0] = (byte) (i >> 24);
  result[1] = (byte) (i >> 16);
  result[2] = (byte) (i >> 8);
  result[3] = (byte) (i /*>> 0*/);

  return result;
}

ByteBufferКлас був розроблений для таких брудних рук завдань , хоча. Насправді приватний java.nio.Bitsвизначає ці допоміжні методи, які використовуються ByteBuffer.putInt():

private static byte int3(int x) { return (byte)(x >> 24); }
private static byte int2(int x) { return (byte)(x >> 16); }
private static byte int1(int x) { return (byte)(x >>  8); }
private static byte int0(int x) { return (byte)(x >>  0); }

3
це буде добре, якщо байт-буфер вже є ... інакше здається, що це займе більше часу, щоб зробити виділення, ніж просто виділити байтовий масив довжиною 4 і зробити переміщення вручну ... але ми, мабуть, говоримо про невеликі відмінності.
Jason S

Екземпляр ByteBuffer можна кешувати; і всередині все це, безумовно, реалізовано зі зрушенням та маскуванням у будь-якому випадку.
Григорій Пакош

4
Це ідеально чудова відповідь. Зауважте, що big-endian є заданим за замовчуванням, а методи "можливі", а аргумент позиції необов'язковий, тому все зводиться до: byte [] result = ByteBuffer.allocate (4) .putInt (0xAABBCCDD) .array ( ); Звичайно, якщо ви робите це неодноразово і об'єднуєте всі результати разом (що звичайно, коли ви робите подібні речі), виділіть один буфер і повторно вставте у нього всі необхідні речі - він буде відслідковувати компенсацію, як ви йдете. Це дійсно надзвичайно корисний клас.
Кевін Бурліон

що це приносить на підписаних типах?
Григорій Пакош

3
Бо хто не знає. PutInt завжди запише 4 байти, незалежно від розміру вхідного числа. Якщо ви хочете лише 2 байти, використовуйте putShort тощо ...
bvdb

36

Використання BigInteger:

private byte[] bigIntToByteArray( final int i ) {
    BigInteger bigInt = BigInteger.valueOf(i);      
    return bigInt.toByteArray();
}

Використання DataOutputStream:

private byte[] intToByteArray ( final int i ) throws IOException {      
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);
    dos.writeInt(i);
    dos.flush();
    return bos.toByteArray();
}

Використання ByteBuffer:

public byte[] intToBytes( final int i ) {
    ByteBuffer bb = ByteBuffer.allocate(4); 
    bb.putInt(i); 
    return bb.array();
}

5
зверніть увагу на порядок байтів
Григорій Пакош

1
Чи видає ByteBuffer неподписаний int?
Arun George

@Pascal Використовуючи ByteBuffer, я спробував з ByteBuffer bb = ByteBuffer.allocate (3); Для цього він дає java.nio.BufferOverflowException, я не розумію, чому він не працює на значення менше 4? Чи можете ви поясніть, будь ласка?
Санджай Джайн

@SanjayJain Ви отримуєте виняток переповнення буфера, тому що вкладиші в Java мають розмір 32-біт або 4 байти, а тому вимагають виділити щонайменше 4 байти пам'яті у вашому ByteBuffer.
шокуюче

@GregoryPakosz має рацію щодо порядку байтів. Його відповідь використовується ByteBufferбільш інтуїтивно, якщо ви маєте справу з
інтом,

31

використовувати цю функцію, вона працює для мене

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

це переводить int у значення байта


Також нічого не варто, що це буде працювати незалежно від найзначнішого біта та більш ефективного порівняно з іншими відповідями. Також може використовувати ">>".
алголічний

1
Таке пряме рішення, безумовно, швидше, ніж викликати будь-який метод бібліотеки. Іноді потрібно просто попрямувати біти безпосередньо з кількома рядками коду, а не робити всі додаткові накладні виклики бібліотечних методів.
David R Tribble

І це добре перетворює між мовами, тому добре для розробки програмного забезпечення для декількох мов.
Координатор

15

Якщо вам подобається Guava , ви можете використовувати його Intsклас:


Для intbyte[]використовуйте toByteArray():

byte[] byteArray = Ints.toByteArray(0xAABBCCDD);

Результат є {0xAA, 0xBB, 0xCC, 0xDD}.


Його зворотний бік fromByteArray()або fromBytes():

int intValue = Ints.fromByteArray(new byte[]{(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD});
int intValue = Ints.fromBytes((byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD);

Результат є 0xAABBCCDD.


8

Ви можете використовувати BigInteger:

Від цілих чисел:

byte[] array = BigInteger.valueOf(0xAABBCCDD).toByteArray();
System.out.println(Arrays.toString(array))
// --> {-86, -69, -52, -35 }

Повертається масив має той розмір, який потрібен для представлення числа, тому він може бути розміром 1, наприклад, 1. Однак розмір не може перевищувати чотирьох байтів, якщо передано інт.

З рядків:

BigInteger v = new BigInteger("AABBCCDD", 16);
byte[] array = v.toByteArray();

Однак вам потрібно буде стежити, якщо перший байт вищий 0x7F(як у цьому випадку), куди BigInteger буде вставляти 0x00 байт на початок масиву. Це потрібно для розрізнення позитивних та негативних значень.


Дякую! Але оскільки це BigInteger, чи вдасться вкрутити правильно? Це цілі числа, які знаходяться поза Integer.MAX_VALUE, але все ще можуть бути представлені лише 4 байтами?
Лютик

1
Це, звичайно, не швидко виконати. ;)
Пітер Лоурі

Це не гарний варіант. Він не тільки може додавати 0x00 байт, але також може знімати провідні нулі.
ZZ Coder

1

Просте рішення, яке належним чином обробляє ByteOrder:

ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(yourInt).array();



1

Це вам допоможе.

import java.nio.ByteBuffer;
import java.util.Arrays;

public class MyClass
{
    public static void main(String args[]) {
        byte [] hbhbytes = ByteBuffer.allocate(4).putInt(16666666).array();

        System.out.println(Arrays.toString(hbhbytes));
    }
}

0

Також можна змінити -

byte[] ba = new byte[4];
int val = Integer.MAX_VALUE;

for(byte i=0;i<4;i++)
    ba[i] = (byte)(val >> i*8);
    //ba[3-i] = (byte)(val >> i*8); //Big-endian

0

Ось метод, який повинен виконати роботу правильно.

public byte[] toByteArray(int value)
{
    final byte[] destination = new byte[Integer.BYTES];
    for(int index = Integer.BYTES - 1; index >= 0; index--)
    {
        destination[i] = (byte) value;
        value = value >> 8;
    };
    return destination;
};

0

Це моє рішення:

public void getBytes(int val) {
    byte[] bytes = new byte[Integer.BYTES];
    for (int i = 0;i < bytes.length; i ++) {
        int j = val % Byte.MAX_VALUE;
        bytes[i] = (j == 0 ? Byte.MAX_VALUE : j);
    }
}

Також Stringметод y:

public void getBytes(int val) {
    String hex = Integer.toHexString(val);
    byte[] val = new byte[hex.length()/2]; // because byte is 2 hex chars
    for (int i = 0; i < hex.length(); i+=2)
        val[i] = Byte.parseByte("0x" + hex.substring(i, i+2), 16);
    return val;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.