Как читать подписанные INT из байтов в Java? - PullRequest
8 голосов
/ 23 августа 2011

У меня есть спецификация, которая гласит, что следующие два байта подписаны int.

Чтобы прочитать это в Java, у меня есть следующее

Когда я читаю подписанное int в Java, используя следующий код, я получаю значение 65449

Логика для расчета без знака

int a =(byte[1] & 0xff) <<8

int b =(byte[0] & 0xff) <<0

int c = a+b 

Я считаю, что это неправильно, потому что если я и с 0xff я получаю беззнаковый эквивалент

поэтому я удалил & 0xff и логику, приведенную ниже

int a = byte[1] <<8
int b = byte[0] << 0
int c = a+b
which gives me the value -343
byte[1] =-1
byte[0]=-87

Я пытался компенсировать эти значения способом чтения спецификации, но это выглядит неправильно. Так как размер кучи не подпадает под это.

Какой правильный способ сделать для вычисления со знаком int в Java?

Вот как идет спецификация

somespec() { xtype 8 uint8 xStyle 16 int16 } xStyle: целое число со знаком, представляющее смещение (в байтах) от начала этой структуры Widget () до начала структуры xStyle (), которая выражает унаследованные стили, определенные виджетом страницы, а также стили, которые применяются конкретно к этому виджету. .

Ответы [ 5 ]

14 голосов
/ 23 августа 2011

Если вы используете 16-битовое значение со знаком, вам нужно short, а 32-битное значение int также может содержать те же значения, но не так естественно.

Похоже, вам нужно 16-разрядное значение со знаком младшего байта.

byte[] bytes = 
short s = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getShort();

или

short s = (short) ((bytes[0] & 0xff) | (bytes[1] << 8));

Кстати: вы можете использовать int, но это не так просто.

// to get a sign extension.
int i = ((bytes[0] & 0xff) | (bytes[1] << 8)) << 16 >> 16;

или

int i = (bytes[0] & 0xff) | (short) (bytes[1] << 8));
4 голосов
/ 23 августа 2011

Предполагая, что байты [1] - это MSB, а байты [0] - это LSB, и вы хотите, чтобы ответом было 16-разрядное целое число со знаком:

short res16 = ((bytes[1] << 8) | bytes[0]);

Затем, чтобы получить 32-битное целое число со знаком:

int res32 = res16;  // sign extends.

Кстати, в спецификации должно быть указано, какой из двух байтов является старшим, а какой младшим. Если это не так и если нет примеров, вы не сможете это реализовать!


Где-то в спецификации будет сказано, как представляется "int16". Вставьте ЭТО часть. Или вставьте ссылку на спецификацию, чтобы мы могли прочитать ее сами.

2 голосов
/ 23 августа 2011

Взгляните на DataInputStream.readInt().Вы можете либо использовать стальной код оттуда, либо просто использовать DataInputStream: оберните им свой входной поток и затем легко читайте типизированные данные.

Для вашего удобства это код:

public final int readInt() throws IOException {
    int ch1 = in.read();
    int ch2 = in.read();
    int ch3 = in.read();
    int ch4 = in.read();
    if ((ch1 | ch2 | ch3 | ch4) < 0)
        throw new EOFException();
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
2 голосов
/ 23 августа 2011

Я не могу скомпилировать это прямо сейчас, но я бы сделал (при условии, * byte1 и byte0 соответствуют типу байтов).

 int result = byte1;
 result = result << 8;
 result = result | byte0;  //(binary OR)
 if (result & 0x8000 == 0x8000) { //sign extension
   result = result | 0xFFFF0000;
 }

, если byte1 и byte0 являются целыми числами, вам нужно сделать `& 0xFF

ОБНОВЛЕНИЕ, потому что Java заставляет выражение if быть логическим

1 голос
/ 23 августа 2011

у вас есть способ найти правильный выход для данного ввода? технически, размер int составляет 4 байта, поэтому, имея всего 2 байта, вы не можете достичь знака бита.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...