Ціле 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

використання ByteBuffer Java NIO дуже просто:

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

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

вихід:

0x65 0x10 0xf3 0x29 

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

146

Як щодо:

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 загалом чудові, але вони не охоплюють та / або не оптимізовані для всіх випадків використання.
mikera

14
домовились; накладні витрати та складність ByteBuffer можуть бути невідповідними порівняно з деякими простими і добре відомими байтовими операціями.
swdunlop

6
Ще я хочу додати, що ви використовували непідписаний оператор правої зміни, >>>а не правий оператор зміни >>( docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html ), тому поведінка може бути не бажаною / як очікувалося, з підписаними або
неподписаними

4
Цей підхід, здається, є в рази швидшим за згадані методи ByteBuffer або BigInteger. Щось ще потрібно врахувати, якщо ви будете робити багато перетворень.
шукач

45

BigInteger.valueOf(1695609641).toByteArray()


2
яка у вас гарантія, що буде вироблятися 4-байтний масив?
MeBigFatGuy

2
Саме те, що написав MeBigFatGuy. Javadoc BigInteger.toByteArray()заявляє: "Масив буде містити мінімальну кількість байтів, необхідних для представлення цього BigInteger ..."
icza

2
Де у запитанні запитується, щоб байтовий масив був фіксованої довжини 4? Залежно від алгоритму мається на увазі, що це частина, ви можете використовувати довжину масиву
vmpn

це набагато динамічніше і має бути правильною відповіддю. Ви можете просто зробити додавання масиву, щоб створити потрібний розмір, якщо вам подобається. Особливо, коли вам слід врахувати значення, підписані Java.
Дроїд Кріс

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;        
}


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;
}

4

Частини нижче працюють принаймні для надсилання int через UDP.

int to byte масив:

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;
}

4
використання ObjectOutputStream невірно. Використовуйте DataOutputStream, використання OOS робить його таким чином, що байтовий масив не має 4 байти.
MeBigFatGuy

2

Оскільки зазвичай ви хочете перетворити цей масив назад в int в більш пізній момент, ось методи перетворення масиву ints в масив байтів і навпаки:

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.


1
integer & 0xFF

за перший байт

(integer >> 8) & 0xFF

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


1

Клас org.apache.hadoop.hbase.util.Bytes має купу зручних методів перетворення байтів [], однак, можливо, ви не хочете додавати всю банку HBase до свого проекту саме для цієї мети. Дивно, що AFAIK від JDK відсутній лише в такому методі, але й у очевидних лайків, таких як com io.


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);

1

Якщо ви використовуєте apache-commons

public static byte[] toByteArray(int value) {
    byte result[] = new byte[4];
    return Conversion.intToByteArray(value, 0, result, 0, 4);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.