ByteBuffer и преобразование между десятичным и шестнадцатеричным

Я хочу взять десятичное целое число, преобразовать его в шестнадцатеричное, а затем разделить байты.

Я так понимаю ByteBuffer это лучший способ сделать это. Целое число не будет превышать 65535, поэтому шестнадцатеричное число гарантированно будет 2 байта. Например, у меня есть целое число 40000 (шестнадцатеричное значение 9C40).

int n1 = 40000;
ByteBuffer b = ByteBuffer.allocate(2);
b.putInt(n1);

Тем не менее, я получаю следующую ошибку при запуске программы:

Исключение в потоке "main" java.nio.BufferOverflowException

Что я делаю неправильно? Не следует ли записывать 9C40 в bb[0] = 9C и b[1] = 40)

Кроме того, как только я пройду мимо этого, если я хочу преобразовать значение, хранящееся в b[0] (от 9C) до десятичного (156), я бы просто использовал следующий код?

int n2 = b.get(0);

3 ответа

Решение

Поскольку вы работаете с ByteBuffer, он хранит количество х выделенных байтов. Теперь вы выделили 2 байта и пытаетесь сохранить тип данных размером 4 байта. Таким образом, буфер выходит за границы, как сказано в сообщении. Если вы хотите сохранить эти данные в двухбайтовом буфере, вы либо используете короткий (16 бит - 2 байта), либо выделяете 4 байта для своего ByteBuffer.

С коротким:

ByteBuffer bb = ByteBuffer.allocate(2);
short myShort = (short) 40000;
bb.putShort(myShort);
System.out.println(String.format("%02X, %02X", bb.get(0), bb.get(1)));

С int:

ByteBuffer bb = ByteBuffer.allocate(4);
int myInt = 40000;
bb.putInt(myInt);
System.out.println(String.format("%02X, %02X", bb.get(2), bb.get(3)));

Выход: 9С, 40

Тип данных, который вы использовали для хранения номера 40000 является int, который требует 4 байта пространства. Да, я знаю, что число не превысит 65535, но компьютер - нет. Вы должны изменить его на соответствующий тип данных, который может быть сохранен в 2 байта.

Этот тип данных short,

Но есть другая проблема, если вы использовали short, вы не можете хранить 40000 в short в Java подписано, поэтому его максимальное значение равно 32767.

Так что хранить ваши 40000, ты должен хранить -25536 вместо этого в shortиз-за переполнения.

short n1 = (short)40000; // this will cause n1 to store -25536
ByteBuffer b = ByteBuffer.allocate(2);
b.putShort(n1);

Теперь пришло время распечатать байты. Байты в Java также подписаны. Так что если вы напечатаете это:

System.out.println(b.get(0));
System.out.println(b.get(1));

Вы получите

-100
64

64 ожидается, так как 64 в гексе это 40, но почему -100? Поскольку байты подписаны, 156 не может быть представлен как 156. 156 в подписанном байте равен -100.

Вместо ByteBuffer я предпочитаю класс Integer, который может конвертировать целочисленное значение в шестнадцатеричную строку, и вы можете получить каждый байт по индексу метода.

Используйте следующий код: int n = 4000; String hex = Integer.toHexString(n);

Таким образом, вы можете получить шестнадцатеричное значение любого целого числа для одного байта, используя метод indexOf() из строки clas.

Вы можете получить возвращаемое шестнадцатеричное значение в виде целого числа, используя метод valueOf() в классе Integer, который принимает два аргумента: один - строка, а другой - основание.

Другие вопросы по тегам