Comment convertir un tableau d'octets en sa valeur numérique (Java)?

89

J'ai un tableau de 8 octets et je veux le convertir en sa valeur numérique correspondante.

par exemple

byte[] by = new byte[8];  // the byte array is stored in 'by'

// CONVERSION OPERATION
// return the numeric value

Je veux une méthode qui effectuera l'opération de conversion ci-dessus.

pirate
la source
4
Qu'entendez-vous par «valeur numérique»? Les octets représentent-ils un nombre entier (long) ou flottant (double) en binaire? Sont-ils la représentation sous forme de chaîne d'un nombre? Ou encore une autre représentation?
starblue
1
Cela a été utile: stackoverflow.com/questions/5399798/…
TacB0sS
NB: le lien de TacB0sS était ce que je recherchais en fait - à la fois la conversion en avant et en arrière.
Jay Taylor
new BigInteger(by).longValue()
Marquis of Lorne

Réponses:

106

En supposant que le premier octet est l'octet le moins significatif:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value += ((long) by[i] & 0xffL) << (8 * i);
}

Le premier octet est-il le plus significatif, alors c'est un peu différent:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value = (value << 8) + (by[i] & 0xff);
}

Remplacez long par BigInteger , si vous avez plus de 8 octets.

Merci à Aaron Digulla pour la correction de mes erreurs.

Mnementh
la source
8
-1 octets sont des valeurs signées! Et remplacez pow () par shift (<<)! "value = (value << 8) + (by [i] & 0xff)"
Aaron Digulla
L'opérateur de décalage (<<) a-t-il une priorité de droite à gauche? Comment fonctionne le code ci-dessus? Cela fonctionne très bien pour moi. Je veux juste savoir le fonctionnement. Merci d'avance
suraj
@Mnementh: L'opérateur de décalage (<<) a-t-il une priorité de droite à gauche? Comment fonctionne le code ci-dessus? Cela fonctionne très bien pour moi. Je veux juste savoir le fonctionnement. Merci d'avance
suraj
5
Au cas où quelqu'un d'autre aurait le même problème que moi, dans le premier exemple, par [i] doit être converti en long, sinon cela ne fonctionne que pour les valeurs inférieures à 2 ^ 32. Autrement dit,value += ((long)by[i] & 0xffL) << (8 * i);
Luc
115

On pourrait utiliser les Buffers qui sont fournis dans le cadre du java.niopackage pour effectuer la conversion.

Ici, le byte[]tableau source a une de longueur 8, qui est la taille qui correspond à une longvaleur.

Tout d'abord, le byte[]tableau est encapsulé dans a ByteBuffer, puis la ByteBuffer.getLongméthode est appelée pour obtenir la longvaleur:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 4});
long l = bb.getLong();

System.out.println(l);

Résultat

4

Je tiens à remercier dfa pour avoir indiqué la ByteBuffer.getLongméthode dans les commentaires.


Bien que cela ne soit peut-être pas applicable dans cette situation, la beauté du Buffers vient de regarder un tableau avec plusieurs valeurs.

Par exemple, si nous avions un tableau de 8 octets et que nous voulions le voir sous forme de deux intvaleurs, nous pourrions envelopper le byte[]tableau dans un ByteBuffer, qui est considéré comme un IntBufferet obtenir les valeurs par IntBuffer.get:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 1, 0, 0, 0, 4});
IntBuffer ib = bb.asIntBuffer();
int i0 = ib.get(0);
int i1 = ib.get(1);

System.out.println(i0);
System.out.println(i1);

Résultat:

1
4
coobird
la source
qu'en est-il de ByteBuffer.wrap (nouvel octet [] {0, 0, 0, 1, 0, 0, 0, 4}). getLong ()? cette méthode devrait lire les 8 octets suivants et les convertir en un long
dfa
@dfa: Merci d'avoir signalé cela, cela semble fonctionner - je vais éditer la réponse. :)
coobird
16

S'il s'agit d'une valeur numérique de 8 octets, vous pouvez essayer:

BigInteger n = new BigInteger(byteArray);

S'il s'agit d'un tampon de caractères UTF-8, vous pouvez essayer:

BigInteger n = new BigInteger(new String(byteArray, "UTF-8"));
Vincent Robert
la source
J'aurais voté pour cette réponse si elle se terminait juste après le premier extrait de code, ou si elle incluait du code pour convertir la chaîne en "valeur numérique". En l'état, la seconde moitié de votre réponse semble être un non-séquentiel.
Laurence Gonsalves
Pas ce que je voulais dire en premier lieu, j'ai changé ma réponse
Vincent Robert
15

Simplement, vous pouvez utiliser ou faire référence à guava lib fournie par google, qui propose des méthodes utilitaires pour la conversion entre un tableau long et un tableau d'octets. Mon code client:

    long content = 212000607777l;
    byte[] numberByte = Longs.toByteArray(content);
    logger.info(Longs.fromByteArray(numberByte));
Chen Yi
la source
9

Vous pouvez également utiliser BigInteger pour les octets de longueur variable. Vous pouvez le convertir en Long, Integer ou Short, selon vos besoins.

new BigInteger(bytes).intValue();

ou pour désigner la polarité:

new BigInteger(1, bytes).intValue();
Jamel Toms
la source
1

Chaque cellule du tableau est traitée comme un entier non signé:

private int unsignedIntFromByteArray(byte[] bytes) {
int res = 0;
if (bytes == null)
    return res;


for (int i=0;i<bytes.length;i++){
    res = res | ((bytes[i] & 0xff) << i*8);
}
return res;
}
Asaf Pinhassi
la source
Juste une note que je devais utiliser 0xFFL, sinon le cast de int 0xFF à long avait beaucoup de bits incorrects définis lorsque j'ai imprimé Long.toHexString (l).
Luke
Vous devez utiliser 0xFFL sinon vous obtenez l'extension de signe.
Gris