Pregunta

Tengo que ser capaz de convertir matrices de bytes a / desde otras matrices de tipo primitivo, pero en lugar de fundición, necesito tipo juegos de palabras . término correcto para la copia en bruto sin poner?

pensé que sería posible hacer lo siguiente:

// 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

Por desgracia, parece que es bb.asIntBuffer() no crear una nueva IntBuffer copiando el contenido de "bit a bit" o "en bruto", sino que crea una nueva "visión" en la ByteBuffer existente. Es por eso que .array() está destinado al fracaso.

I navegado alrededor de las fuentes de JDK, y encontraron pocas clases, que son utilizados por todas estas clases de amortiguación y gustaría hacer las cosas que necesito, pero son internos (como el Unsafe clase).

Si bien creo que mi objetivo podría lograrse envolviendo la memoria intermedia de bytes de alguna ObjectInputStream y leer los valores primitivos de .readInt(), creo que sería una solución desordenado y lento.

Así que, ¿hay otras soluciones posibles sin haciendo aritmética tipo primitivo mágicos (cambiantes, comprobando endians, ...)?

NOTA: Necesito ambas direcciones: byte [12] -> int [3], y int [3] -> byte [12]

¿Fue útil?

Solución

Según el javadoc, array () [1] devuelve array respaldo de la memoria intermedia, que es la matriz que especifica con la llamada para envolver () [2].

Por lo tanto, es necesario crear una nueva matriz con el tipo deseado. Pero la aritmética aún pueden ser manejados a través de las clases de amortiguamiento.

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

Al revés requiere un poco de cálculo por sí mismo.

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

Ver:

[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

Otros consejos

Muchas gracias a wierob por su código para la conversión de byte [] -> int []

He jugado un poco para obtener la dirección opuesta de trabajo.

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 de prueba

{
    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) de salida

[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]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top