2009-04-10 23 views
21

Estoy leyendo 133 paquetes de longitud de serialport, los últimos 2 bytes contienen valores CRC, valor de 2 bytes que he hecho solo (en pocas palabras, creo) usando java. esto lo he hecho,2 bytes a short java

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

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

pero yo no recibo resultado correcto, es problema porque firmado valorada? cómo puedo resolver este problema, ayúdeme, por favor, estoy en problemas

+0

¿Hay alguna razón en particular para usar short en lugar de int? ¿Su valor CRC no está firmado? – akarnokd

Respuesta

54

Recuerde, no tiene que atar en nudos con cambio de bit si no está muy familiarizado con los detalles. Puede utilizar un ByteBuffer para ayudarle a salir:

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

Y viceversa, se puede poner un resumen, a continuación, tire de bytes.

Por cierto, las operaciones a nivel de bit promueven automáticamente los operandos a al menos el ancho de un int. Realmente no existe la noción de "no poder cambiar un byte más de 7 bits" y otros rumores que parecen estar dando vueltas.

+0

tienes razón, se promueve a int así que cambiar por 7 está bien. Pero << 32 no está definido, por lo que no hace nada. – CookieOfFortune

+0

Me parece que el búfer 'converting' de 8192 tamaño tarda casi una eternidad cuando el depurador está conectado al dispositivo. ¿Hay alguna manera de convertir todo el buffer de una vez? –

+1

RE: "no tienes que atarse en nudos con cambio de bit"; en mi experiencia (y es bastante considerable ya que la mayor parte de mi carrera es en comunicaciones), cuando se trata de protocolos de comunicaciones de este tipo, será mejor que te familiarices con las manipulaciones de bits. –

20

Al convertir valores de bytes de una secuencia en valores numéricos en Java, debe tener mucho cuidado con la extensión de signo. Hay una trampa con números negativos (valores de (sin signo) 128-255).

Prueba esto (que funciona si hi y lo son cualquier tipo entero de Java):

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

Me parece que es mejor para ser explícita con los paréntesis en estos casos.

+2

No necesita los moldes para int, eso sucede implícitamente para & operaciones. – starblue

7

Las otras respuestas están bien, pero me gustaría poner énfasis en el tipo:

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

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

El tipo short puede representar valores entre -32768 y 32767. 53328 no se puede muy bien almacenada en definitiva, el uso int en su lugar, ya que le permite almacenar el valor sin firmar hasta ~ 10 Así que no downcast la expresión a corto, ya que le netos el valor firmado.

+0

Aunque, cuando se trata de CRC de 16 bits, solo necesita el patrón de bits correcto; no importa si el valor final de Java está firmado. –

+0

gracias, utilicé '& 0x00FF' desde la primera línea para convertir un byte sin signo en un corto. por ejemplo, establecer 0x87 en un corto dio -121 en lugar de los 135 previstos. – wrapperapps

2

Esto sucede cuando se trata de concatenar bytes (muy sutil)

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

Lo anterior produce 0xFFCA, lo cual es incorrecto. Esto se debe a que b2 es negativo (¡el tipo de byte está firmado!), Lo que significa que cuando se convertirá en tipo int para el bit-wise | operación, será rellenado a la izquierda con 0xF!

Por lo tanto, se debe recordar para enmascarar-cabo los bytes acolchadas para que sin duda será cero:

short s = (short) (b1<<8 | b2 & 0xFF); 
0

puede convertir 2 bytes a un cortocircuito en una forma más legible y elegante.

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

El primer byte es el byte más significativo.