2011-10-01 15 views
89

Desidero memorizzare alcuni dati in matrici di byte in Java. In pratica solo numeri che possono richiedere fino a 2 byte per numero.Convertire un array di byte in intero in Java e viceversa

Mi piacerebbe sapere come posso convertire un intero in un array di byte lungo 2 byte e viceversa. Ho trovato molte soluzioni su google, ma la maggior parte di esse non spiega cosa succede nel codice. C'è un sacco di cose che non riesco a capire, quindi apprezzerei una spiegazione di base.

+3

Quanto * * fai a capire su po spostando? Sembra proprio che la domanda sia davvero "cosa fa il bit shifting" più della conversione in array di byte, in realtà - se in realtà vuoi capire come funzionerebbe la conversione. –

+1

(Giusto per chiarire, sto bene con entrambe le domande, ma vale la pena chiarire * quale * domanda a cui vuoi veramente rispondere. Probabilmente otterrai una risposta che ti è più utile in questo modo.) –

+0

Okay capito il tuo punto! Grazie per l'osservazione. So che bit shifting non ho ancora capito a cosa serve per la conversione di array di byte. – Chris

risposta

158

Utilizzare le classi disponibili nello spazio dei nomi java.nio, in particolare ByteBuffer. Può fare tutto il lavoro per te.

byte[] arr = { 0x00, 0x01 }; 
ByteBuffer wrapped = ByteBuffer.wrap(arr); // big-endian by default 
short num = wrapped.getShort(); // 1 

ByteBuffer dbuf = ByteBuffer.allocate(2); 
dbuf.putShort(num); 
byte[] bytes = dbuf.array(); // { 0, 1 } 
4

Un'implementazione di base sarebbe qualcosa di simile:

public class Test { 
    public static void main(String[] args) { 
     int[] input = new int[] { 0x1234, 0x5678, 0x9abc }; 
     byte[] output = new byte[input.length * 2]; 

     for (int i = 0, j = 0; i < input.length; i++, j+=2) { 
      output[j] = (byte)(input[i] & 0xff); 
      output[j+1] = (byte)((input[i] >> 8) & 0xff); 
     } 

     for (int i = 0; i < output.length; i++) 
      System.out.format("%02x\n",output[i]); 
    } 
} 

Al fine di comprendere cose che potete leggere questo articolo WP: http://en.wikipedia.org/wiki/Endianness

Il codice sorgente di cui sopra sarà in uscita 34 12 78 56 bc 9a. I primi 2 byte (34 12) rappresentano il primo numero intero, ecc. Il codice sorgente precedente codifica gli interi in formato little endian.

92
byte[] toByteArray(int value) { 
    return ByteBuffer.allocate(4).putInt(value).array(); 
} 

byte[] toByteArray(int value) { 
    return new byte[] { 
     (byte)(value >> 24), 
     (byte)(value >> 16), 
     (byte)(value >> 8), 
     (byte)value }; 
} 

int fromByteArray(byte[] bytes) { 
    return ByteBuffer.wrap(bytes).getInt(); 
} 
// packing an array of 4 bytes to an int, big endian 
int fromByteArray(byte[] bytes) { 
    return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF); 
} 

Nell'imballare byte Acceso in un int, ciascun byte deve essere mascherato perché è registrati esteso a 32 bit (anziché zero esteso) dovute alla regola promozione aritmetica (descritto in JLS, conversioni e promozioni).

C'è un interessante puzzle relativo a questo descritto in Java Puzzlers ("Una grande delizia in ogni byte") di Joshua Bloch e Neal Gafter. Quando si confrontano un valore di byte per un valore int, il byte è segno-esteso ad un int e poi questo valore viene confrontato con l'altro int

byte[] bytes = (…) 
if (bytes[0] == 0xFF) { 
    // dead code, bytes[0] is in the range [-128,127] and thus never equal to 255 
} 

Si ricorda che tutti i tipi numerici sono firmati in Java con l'eccezione a char essere un tipo intero senza segno a 16 bit.

+3

Cosa succede se il valore è maggiore di 127 ... – aProgrammer

+0

@Amit Non importa. –

+0

Penso che '& 0xFF's non siano necessari. –

30

È inoltre possibile utilizzare BigInteger per byte di lunghezza variabile. Puoi convertirlo in long, int o short, a seconda delle tue esigenze.

new BigInteger(bytes).intValue(); 

o per indicare la polarità:

new BigInteger(1, bytes).intValue(); 

Per ottenere byte indietro solo:

new BigInteger(bytes).toByteArray() 
+0

È utile per me, grazie – Jaycee

-3

Credo che questo sia un modo migliore di lanciare a int

public int ByteToint(Byte B){ 
     String comb; 
     int out=0; 
     comb=B+""; 
     salida= Integer.parseInt(comb); 
     out=out+128; 
     return out; 
    } 

primo comvert byte a String

comb=B+""; 

passo successivo è COMVERT ad un int

out= Integer.parseInt(comb); 

ma byte è di rabbia di -128 a 127 per questa reasone, penso che sia meglio utilizzare la rabbia da 0 a 255 e avete solo bisogno di fare questo:

out=out+256; 
+0

Questo è sbagliato. Considera il byte 0x01. Il tuo metodo produrrà 129 che è sbagliato. 0x01 dovrebbe restituire il numero intero 1. Dovresti aggiungere solo 128 se il numero intero che ottieni da parseInt è negativo. – disklosr

+0

Intendevo dire che dovresti aggiungere 256 e non 128. Impossibile modificarlo in seguito. – disklosr

+0

post modificato per aggiungere 256 come potrebbe essere utile per gli altri! – apmartin1991

1
/** length should be less than 4 (for int) **/ 
public long byteToInt(byte[] bytes, int length) { 
     int val = 0; 
     if(length>4) throw new RuntimeException("Too big to fit in int"); 
     for (int i = 0; i < length; i++) { 
      val=val<<8; 
      val=val|(bytes[i] & 0xFF); 
     } 
     return val; 
    } 
Problemi correlati