Domanda

Devo essere in grado di convertire array di byte in/da altri array di tipo primitivo, ma invece di eseguire il casting, ho bisogno tipo giochi di parole. Termine corretto per copia grezza senza fusione?

Pensavo che sarebbe stato possibile fare quanto segue:

// idea: byte[12] -> int[3], and int[3] -> byte[12]

int[] ints;

ByteBuffer bb = ByteBuffer.wrap(
    new byte[]{ 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3 });
IntBuffer ib = bb.asIntBuffer();

ints = ib.array(); // java.lang.UnsupportedOperationException
ints = ib.duplicate().array(); // java.lang.UnsupportedOperationException

Sfortunatamente, sembra che bb.asIntBuffer() È non creando un nuovo IntBuffer copiando il contenuto "bitwise" o "raw", ma crea una nuova "vista" sul ByteBuffer esistente.Ecco perché .array() è destinato a fallire.

Ho cercato nei sorgenti di JDK e ho trovato poche classi utilizzate da tutte queste classi buffer e volevo fare le cose di cui ho bisogno, ma sono interne (come il class Unsafe).

Mentre penso che il mio obiettivo potrebbe essere raggiunto avvolgendo il buffer dei byte in alcuni ObjectInputStream e leggere i valori primitivi di .readInt(), Penso che sarebbe una soluzione complicata e lenta.

Quindi, ci sono altre soluzioni possibili senza fare calcoli aritmetici magici di tipo primitivo (spostamento, controllo degli endian, ...)?

NOTA:Ho bisogno di entrambe le direzioni:byte[12] -> int[3] e int[3] -> byte[12]

È stato utile?

Soluzione

Secondo il javadoc, array () [1] Restituisce Array supporto del tampone che è la matrice si specifica con la chiamata per avvolgere () [2].

Quindi, è necessario creare un nuovo array con il tipo desiderato. Ma l'aritmetica possono ancora essere gestiti tramite le classi Buffer.

ByteBuffer bb = ByteBuffer.wrap(new byte[]{ 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3 });
IntBuffer ib = bb.asIntBuffer();

int[] intArray = new int[ib.limit()];
ib.get(intArray);

richiede indietro un po 'di calcoli da soli.

ByteBuffer newBb = ByteBuffer.allocate(intArray.length*4);
newBb.asIntBuffer().put(intArray);
byte[] byteArray = newBb.array();

See:

[1] http://java.sun.com/javase/6/docs/api/java/nio/ByteBuffer.html#array%28%29

[2] http://java.sun.com/javase/6/docs/api/java/nio/ByteBuffer.html#wrap%28byte []% 29

Altri suggerimenti

Molte grazie a wierob per il suo codice per la conversione byte[]->int[] !

Ho giocato un po' per far funzionare la direzione opposta.

1)API

// byte[] -> int[]
public static int[] punnedToInteger(byte[] in){
    ByteBuffer bb = ByteBuffer.wrap(in);
    IntBuffer pb = bb.asIntBuffer();

    int[] out = new int[pb.limit()];
    pb.get(out);

    return out;
}

// int[] -> byte[]
public static byte[] punnedFromInteger(int[] in){
    byte[] out = new byte[in.length * Integer.SIZE / Byte.SIZE];
    ByteBuffer bb = ByteBuffer.wrap(out);

    for(int i=0; i<in.length; ++i){
        bb.putInt(in[i]);
    }

    return out;
}

2) Caso di prova

{
    byte[] bytes = new byte[]{ 0,0,0,1, 0,0,1,0, 0,1,0,0, 1,0,0,0 };
    int[] ints = punnedToInteger(bytes);
    System.out.println(Arrays.toString(bytes));
    System.out.println(Arrays.toString(ints));
    System.out.println();
}
{
    int[] ints = new int[]{ 1, 256, 65536, 16777216 };
    byte[] bytes = punnedFromInteger(ints);
    System.out.println(Arrays.toString(ints));
    System.out.println(Arrays.toString(bytes));
    System.out.println();
}

3) Uscita

[0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0]
[1, 256, 65536, 16777216]

[1, 256, 65536, 16777216]
[0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top