2 байта в короткую java

я читаю пакет длиной 133 из последовательного порта, последние 2 байта содержат значения CRC, значение 2 байта, которое я сделал одиночным (я думаю, коротким), используя java. это то, что я сделал,

short high=(-48 & 0x00ff);
short low=80;

short c=(short) ((high<<8)+low);

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


person Community    schedule 10.04.2009    source источник
comment
Есть ли особая причина, по которой вы используете short вместо int? Разве ваше значение CRC не беззнаковое?   -  person akarnokd    schedule 08.07.2009


Ответы (6)


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

ByteBuffer bb = ByteBuffer.allocate(2);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.put(firstByte);
bb.put(secondByte);
short shortVal = bb.getShort(0);

И наоборот, можно поставить шорт, потом вытащить байты.

Кстати, побитовые операции автоматически продвигают операнды как минимум до ширины int. На самом деле нет понятия «не разрешено сдвигать байт более чем на 7 бит» и других слухов, которые, кажется, ходят.

person Neil Coffey    schedule 10.04.2009
comment
вы правы, он продвигается до int, поэтому сдвиг на 7 в порядке. Но ‹‹ 32 не определено, поэтому ничего не делает. - person CookieOfFortune; 10.04.2009
comment
Я обнаружил, что «преобразование» буфера размером 8192 занимает почти вечность, когда к устройству подключен отладчик. Есть ли способ преобразовать весь буфер за один раз? - person Daniel Mošmondor; 27.03.2013
comment
RE: вам не нужно связывать себя узлами с переключением битов; по моему опыту (а он весьма значителен, так как большая часть моей карьеры связана с коммуникациями), когда имеешь дело с протоколами связи такого рода, тебе лучше чертовски познакомиться с битовыми манипуляциями. - person Lawrence Dol; 10.04.2014
comment
Лоуренс, в целом согласен. Но, с другой стороны, в этом конкретном случае класс ByteBuffer предоставляет API, специально разработанный для того, чтобы делать то, что пытается сделать плакат... - person Neil Coffey; 11.04.2014
comment
Очень удачно поставленный, подходящий молоток... Знаешь, когда вопрос не такой тривиальный - person Blake Neal; 07.06.2018

При преобразовании байтовых значений из потока в числовые значения в Java вы должны быть очень осторожны с расширением знака. Есть ловушка с отрицательными числами (значения от (без знака) 128-255).

Попробуйте это (это работает, если hi и lo - любой целочисленный тип Java):

short val=(short)(((hi & 0xFF) << 8) | (lo & 0xFF));

Я считаю, что в таких случаях лучше всего указывать круглые скобки.

person Lawrence Dol    schedule 10.04.2009
comment
Вам не нужны приведения к int, это происходит неявно для операций &. - person starblue; 10.04.2009

Это происходит при попытке объединить байты (очень тонко)

byte b1 = (byte) 0xAD;
byte b2 = (byte) 0xCA;
short s = (short) (b1<<8 | b2);

Вышеприведенное выдает 0xFFCA, что неверно. Это связано с тем, что b2 является отрицательным (тип байта знаковый!), а это означает, что когда он будет преобразован в тип int для побитового | операция, она будет дополнена слева 0xF!

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

short s = (short) (b1<<8 | b2 & 0xFF);
person Lake    schedule 06.07.2016

Другие ответы в порядке, но я хотел бы сделать акцент на типе:

short high=(-48 & 0x00ff);
short low=80;

int c= ((high & 0xFF) << 8) | (low & 0xFF);

Тип short может представлять значения от -32768 до 32767. 53328 не может быть хорошо сохранен в краткости, вместо этого используйте int, так как он позволяет хранить значение без знака до ~109, поэтому не понижайте выражение короче, так как это принесет вам подписанное значение.

person akarnokd    schedule 08.07.2009
comment
Хотя при работе с 16-битным CRC вам нужен только правильный битовый шаблон; не имеет значения, подписано ли окончательное значение Java. - person Lawrence Dol; 10.04.2014
comment
спасибо, я использовал & 0x00FF из первой строки, чтобы преобразовать беззнаковый байт в короткий. например, установка 0x87 на короткую дала -121 вместо предполагаемых 135. - person wrapperapps; 15.02.2018

Вы можете преобразовать 2 байта в короткие более читабельным и элегантным способом.

short s = ByteBuffer.wrap(new byte[]{0x01, 0x02}).getShort();
// now s equals 258 = 256 + 2

Первый байт является самым значащим байтом.

person Mariusz Wiazowski    schedule 27.02.2018
comment
в моих тестах это быстрее, чем ручное преобразование или другой ответ здесь с использованием ByteBuffers (с фиксированным распределением). - person brimborium; 15.07.2021

Это работает для меня

short temp = ;
result[0] = (byte) ((temp >>> 8) & 0xFF);
result[1] = (byte)((temp) & 0xFF);
person bhardwaj    schedule 11.12.2020