Представление числа в массиве байтов (программирование на 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();
}

вы пробовали кастинг на байт ? например,

sendData[1] = (byte)0x94;

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