2011-01-22 5 views
21

Ho un byte[] che ho letto da un file e voglio ottenere uno int da due byte in esso. Ecco un esempio:Leggi due byte in un numero intero?

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 

questo dovrebbe rendere value uguale 0x0110, o 272 in decimale. Ma ovviamente, byte[].getInt() non esiste. Come posso portare a termine questo compito?

L'array sopra riportato è solo un esempio. I valori reali sono sconosciuti per me.

+0

il motivo per cui le risposte funzionano è che i byte vengono promossi in numeri interi nel caso in cui sia ciò che causa problemi di comprensione. "byte [2] * 256" non rientra in un byte, ma non è un problema perché "256" è un numero intero, ecc. – SyntaxT3rr0r

+1

possibile duplicato di [Converti 4 byte in int] (http://stackoverflow.com)/questions/2383265/convert-4-bytes-to-int) – finnw

risposta

36

Si dovrebbe solo optare per la semplice:

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

Si potrebbe anche scrivere il proprio funzione di supporto getBytesAsWord (byte[] bytes, int start) per darvi la funzionalità se non si desidera che i calcoli infarcendo il codice, ma penso che sarebbe probabilmente essere eccessivo.

+1

Idealmente dovrebbe essere (b1 << 8) | (b2 & 0x00ff) Se il valore del secondo byte è maggiore di 128, la conversione precedente fornisce un valore errato, poiché java considera il byte come negativo int. – Gopi

+0

Perché il '0xff'? In altre parole, qual è la differenza con 'byte [0] << 8 | byte [1] '? – arve0

+1

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

1

In alternativa, è possibile utilizzare:

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

No: restituirà un numero negativo int se i byte [2] sono maggiori di 0x7f. È richiesto "& 0xff" dalla risposta di paxdiablo. – Francois

6

Prova:

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

La tua domanda non ha indicato il significato dei due args (2,4). 2 e 4 non hanno senso nel tuo esempio come indici dell'array per trovare ox01 e 0x10, ho intuito che volevi prendere due elementi consecutivi, una cosa comune da fare, quindi ho usato off e off + 1 nel mio metodo.

Non è possibile estendere la classe byte [] in java, quindi non è possibile avere un metodo bytes.getInt, quindi ho creato un metodo statico che utilizza il byte [] come primo argomento.

Il 'trucco' per il metodo è che i byte vengono 8 bit firmato interi e valori superiori 0x80 sono negative e sarebbe segno esteso (cioè 0xFFFFFF80 quando viene utilizzato come un int). Ecco perché è necessario il mascheramento '0x0xFF'. lo '< < 8' sposta il byte più significativo a 8 bit rimasti. Il '|' combina i due valori - proprio come farebbe '+'. L'ordine degli operatori è importante perché < < ha la precedenza più alta, seguito da & seguito da | - quindi non sono necessarie parentesi.

+0

Thx per questa bella spiegazione. Per la stessa cosa, ma con valore firmato, ho usato: 'return arr [off] << 8 | arr [off + 1] &0xFF; ' –

0

È possibile utilizzare ByteBuffer. Ha il metodo getInt che stai cercando e molti altri metodi utili

2

Ecco un modo semplice e affidabile.

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 classe Google Base16 proviene da Guava-14.0.1.

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