Java конвертировать 4 байта в int - PullRequest
13 голосов
/ 15 мая 2010

Мне было интересно, если решение для этого документированного здесь все еще является решением или есть какой-то другой способ получить int из 4 байтов?

спасибо.

РЕДАКТИРОВАТЬ: я получаю байт [] из сокетов .read

РЕДАКТИРОВАТЬ: int recvMsgSize = in.read(Data, 0, BufferSize); если recvMsgSize равен -1, я знаю, что соединение было разорвано.

как я могу обнаружить это, когда я использую DataInputStream вместо InputStream?

спасибо.

РЕДАКТИРОВАТЬ: извинения за то, что вы йо-йо в отношении принятия правильного ответа. но после обновленного окончательного ответа mihi может показаться, что метод является надежным и сокращает расширенное кодирование и, по моему мнению, лучшую практику.

Ответы [ 5 ]

17 голосов
/ 15 мая 2010

Вы должны быть очень осторожны с любым расширяющимся преобразованием и числовым продвижением, но код ниже преобразует 4 byte в int:

    byte b1 = -1;
    byte b2 = -2;
    byte b3 = -3;
    byte b4 = -4;
    int i = ((0xFF & b1) << 24) | ((0xFF & b2) << 16) |
            ((0xFF & b3) << 8) | (0xFF & b4);
    System.out.println(Integer.toHexString(i)); // prints "fffefdfc"

См. Также

16 голосов
/ 15 мая 2010

Если они уже есть в массиве byte[], вы можете использовать:

int result = ByteBuffer.wrap(bytes).getInt();

или, если у вас есть guava-библиотеки Google на вашем пути к классам, у вас есть ярлык:

int result = Ints.fromByteArray(array);

, что имеет то преимущество, что у вас есть аналогичные API для других типов (Longs.fromByteArray, Shorts.fromByteArray и т. Д.).

8 голосов
/ 15 мая 2010

В зависимости от того, откуда вы получаете эти 4 байта:

http://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readInt()

http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#getInt(int)

Конечно, вы все равно можете сделать это вручную, но в большинстве случаев, используя один из них (если вам нужно преобразовать байтовый массив с большим количеством байтов, вы можете использовать DataInputStream, например, ByteArrayInputStream ) проще.

Редактировать : Если вам нужно изменить порядок байтов, вам придется использовать ByteBuffer, либо самостоятельно инвертировать байты, либо выполнить преобразование самостоятельно, поскольку DataInput не поддерживает изменение порядка байтов.

Edit2 : Когда вы получаете их из входного потока сокета, я помещаю его в DataInputStream и использую его для чтения всех видов данных. Тем более что InputStream.read (byte []) не гарантирует заполнение всего байтового массива ... DataInputStream.readFully делает.

DataInputStream in = new DataInputStream(socket.getInputStream());
byte aByte = in.readByte();
int anInt = in.readInt();
int anotherInt = in.readInt();
short andAShort = in.readShort(); // 11 bytes read :-)
byte[] lotOfBytes = new byte[anInt];
in.readFully(lotOfBytes);

Edit3 : при многократном чтении из потока они продолжат чтение с того места, где вы остановились, т.е. е. aByte будет байтом 0, anInt будет байтами с 1 по 4, anotherInt будет байтами с 5 по 8 и т. д. readFully продолжит чтение после всего этого и будет блокироваться, пока не прочитает lotOfbytes.

Когда поток останавливается (соединение обрывается), вы получите EOFException вместо -1, поэтому, если вы получите -1, int действительно будет -1.

Если вы вообще не хотите разбирать какие-либо байты, вы можете пропустить () их. Синтаксический анализ одного байта двумя различными способами невозможен с DataInputStream (то есть сначала читается int из байтов 0–3, затем один из байтов 2–5), но обычно это также не требуется.

* +1032 * Пример: * 1 033 *
// read messages (length + data) until the stream ends:
while (true) {
int messageLength;
try {
    messageLength = in.readInt(); // bytes 0 to 3
} catch (EOFException ex) {
    // connection dropped, so handle it, for example
    return;
}
byte[] message = new byte[messageLength];
in.readFully(message);
// do something with the message.
}
// all messages handled.

Надеюсь, что это ответит на ваши дополнительные вопросы.

0 голосов
/ 15 мая 2010

Решение в функциональном стиле (только для разнообразия, не очень удобное в использовании):

private int addByte (int base, byte appendix) {
    return (base << 4) + appendix;
}

public void test() {
    byte b1 = 5, b2 = 5, byte b3 = 0, b4 = 1;
    int result = addByte (addByte (addByte (addByte (0, b1), b2), b3), b4);
}
0 голосов
/ 15 мая 2010

Как сказал Михи, это зависит от того, откуда вы получаете эти байты, но этот код может быть полезен:

int myNumber = (((int)byteOne) << 0) |
    (((int)byteTwo) << 8) |
    (((int)byteThree) << 16) |
    (((int)byteFour) << 24);
...