2011-01-22 12 views
21

Tengo un byte[] que he leído de un archivo, y quiero obtener un int de dos bytes. He aquí un ejemplo:¿Lees dos bytes en un número entero?

byte[] bytes = new byte[] {(byte)0x00, (byte)0x2F, (byte)0x01, (byte)0x10, (byte)0x6F}; 
int value = bytes.getInt(2,4); //This method doesn't exist 

Esto debería hacer value igual a 0x0110 o 272 en decimal. Pero obviamente, byte[].getInt() no existe. ¿Cómo puedo lograr esta tarea?

La matriz anterior es solo un ejemplo. Los valores reales son desconocidos para mí.

+0

la razón por la que funcionan las respuestas es que los bytes se promueven a números enteros en caso de que eso sea lo que le causa problemas para entender. "bytes [2] * 256" no cabe en un byte, pero no es un problema porque "256" es un número entero, etc. – SyntaxT3rr0r

+1

posible duplicado de [Convertir 4 bytes en int] (http://stackoverflow.com)/questions/2383265/convert-4-bytes-to-int) – finnw

Respuesta

36

Usted sólo debe optar por la sencilla:

int val = ((bytes[2] & 0xff) << 8) | (bytes[3] & 0xff); 

Incluso se puede escribir su propia función auxiliar getBytesAsWord (byte[] bytes, int start) para darle la funcionalidad si no desea que los cálculos salpicando su código pero creo que probablemente ser excesivo

+1

Idealmente debería ser (b1 << 8) | (b2 y 0x00ff) Si el valor del segundo byte es mayor que 128, la conversión anterior da un valor incorrecto, ya que java considera el byte como negativo int. – Gopi

+0

¿Por qué el '0xff'? En otras palabras, ¿cuál es la diferencia con 'bytes [0] << 8 | bytes [1] '? – arve0

+1

@ arve0 ver http://stackoverflow.com/a/11380077/1685098 –

1

Alternativamente, se puede utilizar:

int val = (bytes[2] << 8) + bytes[3] 
+1

No: devolverá un int negativo si bytes [2] es mayor que 0x7f. Se requiere el "& 0xff" de la respuesta de paxdiablo. – Francois

6

Probar:

public static int getInt(byte[] arr, int off) { 
    return arr[off]<<8 &0xFF00 | arr[off+1]&0xFF; 
} // end of getInt 

Su pregunta no indicó cuáles son los dos argumentos (2,4) significaban. 2 y 4 no tienen sentido en tu ejemplo como índices en la matriz para encontrar ox01 y 0x10, supuse que querías tomar dos elementos consecutivos, algo común que hacer, así que usé off y off + 1 en mi método.

No puede extender la clase byte [] en java, por lo que no puede tener un método bytes.getInt, por lo que hice un método estático que usa el byte [] como primer arg.

El 'truco' para el método es que los bytes de 8 bits firmaron enteros y valores sobre 0x80 son negativos y sería signo extendido (es decir 0xFFFFFF80 cuando se utiliza como un int). Es por eso que se necesita la máscara '& 0xFF'. el '< < 8' desplaza el byte más significativo de 8 bits restantes. El '|' combina los dos valores, al igual que '+'. El orden de los operadores es importante porque < < tiene la precedencia más alta, seguido de & seguido de | - por lo tanto, no se necesitan paréntesis.

+0

Gracias por esta buena explicación. Para la misma cosa pero con valor firmado, utilicé: 'return arr [off] << 8 | arr [off + 1] &0xFF; ' –

0

Puede usar ByteBuffer. Tiene el método getInt que está buscando y muchos otros métodos útiles

2

Aquí hay una buena manera simple y confiable.

ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4); 
    // by choosing big endian, high order bytes must be put 
    // to the buffer before low order bytes 
    byteBuffer.order(ByteOrder.BIG_ENDIAN); 
    // since ints are 4 bytes (32 bit), you need to put all 4, so put 0 
    // for the high order bytes 
    byteBuffer.put((byte)0x00); 
    byteBuffer.put((byte)0x00); 
    byteBuffer.put((byte)0x01); 
    byteBuffer.put((byte)0x10); 
    byteBuffer.flip(); 
    int result = byteBuffer.getInt(); 
0

La clase Google Base16 es de Guava-14.0.1.

new BigInteger(com.google.common.io.BaseEncoding.base16().encode(bytesParam),16).longValue(); 
Cuestiones relacionadas