ByteBuffer и преобразование между десятичным и шестнадцатеричным
Я хочу взять десятичное целое число, преобразовать его в шестнадцатеричное, а затем разделить байты.
Я так понимаю ByteBuffer
это лучший способ сделать это. Целое число не будет превышать 65535, поэтому шестнадцатеричное число гарантированно будет 2 байта. Например, у меня есть целое число 40000 (шестнадцатеричное значение 9C40).
int n1 = 40000;
ByteBuffer b = ByteBuffer.allocate(2);
b.putInt(n1);
Тем не менее, я получаю следующую ошибку при запуске программы:
Исключение в потоке "main" java.nio.BufferOverflowException
Что я делаю неправильно? Не следует ли записывать 9C40 в b
(с b[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, который принимает два аргумента: один - строка, а другой - основание.