web-dev-qa-db-fra.com

Convertir un tableau d'octets en entier en Java et inversement

Je souhaite stocker des données dans des tableaux d'octets en Java. Fondamentalement, juste des nombres qui peuvent prendre jusqu'à 2 octets par numéro.

Je voudrais savoir comment je peux convertir un entier en un tableau d'octets long de 2 octets et vice versa. J'ai trouvé beaucoup de solutions sur Google, mais la plupart d'entre elles n'expliquent pas ce qui se passe dans le code. Il y a beaucoup de choses changeantes que je ne comprends pas vraiment, alors j'apprécierais une explication de base.

111
Chris

Utilisez les classes présentes dans le Java.nio namespace, en particulier le ByteBuffer . Il peut faire tout le travail pour vous.

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 }
191
Jeff Mercado
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);
}

Lors de la compression d'octets signés dans un int, chaque octet doit être masqué car il est étendu à 32 bits (plutôt qu'à zéro) en raison de la règle de promotion arithmétique (décrite dans JLS, Conversions et Promotions).

Il existe un casse-tête intéressant en rapport avec cela décrit dans Java Puzzlers ("Un grand plaisir dans chaque octet") de Joshua Bloch et Neal Gafter. Lorsque vous comparez une valeur d'octet à une valeur int, l'octet est étendu à un int, puis cette valeur est comparée à l'autre int.

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

Notez que tous les types numériques sont signés en Java, sauf que char est un type entier non signé de 16 bits.

108

Vous pouvez également utiliser BigInteger pour les octets de longueur variable. Vous pouvez le convertir en long, int ou short, selon vos besoins.

new BigInteger(bytes).intValue();

ou pour désigner la polarité:

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

Pour récupérer des octets, il suffit de:

new BigInteger(bytes).toByteArray()
45
Jamel Toms

Une implémentation de base ressemblerait à ceci:

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]);
    }
}

Pour comprendre certaines choses, vous pouvez lire cet article WP: http://en.wikipedia.org/wiki/Endianness

Le code source ci-dessus générera 34 12 78 56 bc 9a. Les deux premiers octets (34 12) représentent le premier entier, etc. Le code source ci-dessus code des entiers au format little endian.

4
prekageo
/** 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;
    }
1
Dhaval Rami

Quelqu'un avec une exigence où ils doivent lire des bits, disons que vous devez lire seulement de 3 bits, mais vous avez besoin d'un entier signé, puis utilisez ce qui suit:

data is of type: Java.util.BitSet

new BigInteger(data.toByteArray).intValue() << 32 - 3 >> 32 - 3

Le nombre magique 3 peut être remplacé par le nombre de bits (pas d'octets) que vous utilisez.

0
Vishrant