Представление числа в массиве байтов (программирование на java)
Я пытаюсь представить номер порта 9876 (или 0x2694 в hex) в двухбайтовом массиве:
class foo {
public static void main (String args[]) {
byte[] sendData = new byte[1];
sendData[0] = 0x26;
sendData[1] = 0x94;
}
}
но я получаю предупреждение о возможной потере точности:
foo.java:5: possible loss of precision
found : int
required: byte
sendData[1] = 0x94;
^
1 error
Как я могу представить число 9876 в двухбайтовом массиве без потери точности?
Примечание: я выбрал код @Björn в качестве правильного ответа, но код @glowcoder также работает хорошо. Это просто другой подход к той же проблеме. Спасибо все!
7 ответов
мой первый ответ будет bitshifting, но на второй мысли я думаю, что использование outputstreams может быть лучше и проще понять. Обычно я избегаю кастинга, но если вы не собираетесь для общего решения, я думаю, что это было бы хорошо. :)
использование потоков, общее решение:
public byte[] intToByteArray(final int i) throws java.io.IOException {
java.io.ByteArrayOutputStream b = new java.io.ByteArrayOutputStream();
java.io.DataOutputStream d = new java.io.DataOutputStream(b);
d.writeInt(i);
d.flush();
return b.toByteArray();
}
и обратить его:
public int byteArrayToInt(final byte[] b) throws IOException {
java.io.ByteArrayInputStream ba = new java.io.ByteArrayInputStream(b);
java.io.DataInputStream d = new java.io.DataInputStream(ba);
return d.readInt();
}
0x94 - 148 в десятичном формате, что превышает диапазон байтов в java (от -128 до 127). Вы можете сделать одно из следующих действий:
1) приведение будет работать нормально, потому что оно сохранит двоичное представление (никакие значимые биты не усекаются для 0x00 до 0xFF):
sendData[1] = (byte)0x94;
2) двоичное представление 0x94 в виде подписанного байта -108 (- 0x6C), поэтому следующее будет иметь тот же эффект:
sendData[1] = -0x6C; //or -108 in decimal
Бьерн дал хороший общий ответ с использованием потоков. Вы также можете сделать то же самое используя java.nio.ByteBuffer
что приводит к немного меньшему коду, и вы также можете контролировать endianess (порядок байтов) вывода.
чтобы создать массив байтов:
public static byte[] toByteArray(int bits) {
ByteBuffer buf = ByteBuffer.allocate(4);
buf.putInt(bits);
return buf.array();
}
чтобы изменить это:
public static int fromByteArray(byte[] b) {
ByteBuffer buf = ByteBuffer.wrap(b);
return buf.getInt();
}
вы должны привести к (байту), поскольку тип номера по умолчанию в java-int, который больше байта. Пока значение вписывается в байт, это нормально для приведения.
попробуйте это:
sendData[0] =(byte)0x26
sendData[1] =(byte)0x94
или такой:
sendData[0] =(byte)38
sendData[1] =(byte)148
вы должны привести данные в байт, чтобы назначить его байту!
что не означает, что вы потеряли точность, просто писать 0x26
означает компилятор int для Java..
но также обратите внимание: диапазон байта от -128 до 127, поэтому в случае 0x94=148
он будет представлен после байтового литья как "-108", поэтому он не будет работать правильно в математических вычислениях..
Это потому, что все в Java-это подпись. 0x94 (148) больше байта.Массив(2^7-1).
что нужно
public static byte[] intToByteArray(int value) {
byte[] b = new byte[4];
for (int i = 0; i < 4; i++) {
int offset = (b.length - 1 - i) * 8;
b[i] = (byte) ((value >>> offset) & 0xFF);
}
return b;
}