Frage

Ich brauche zu konvertieren Byte-Arrays zu / von anderem primitivem Typ-Arrays zu können, aber statt Casting, ich brauche Typ punning . Die korrekte Bezeichnung für rohe Kopie ohne Gießen?

Ich dachte, es wäre möglich, folgendes zu tun:

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

Leider scheint es, dass bb.asIntBuffer() ist nicht ein neues IntBuffer Erstellung durch Kopieren des Inhalts „bitweise“ oder „roh“, sondern schafft eine neue „Sicht“ auf die bestehenden ByteBuffer. Deshalb .array() sollte zum Scheitern verurteilt.

ich sucht in JDK Quellen um und fand einige Klassen, die von allen diesen Pufferklassen verwendet werden und würde tun, um die Dinge, die ich brauche, aber sind interne (wie die Klasse Unsafe).

Während ich denke, dass mein Ziel durch Wickeln des Bytepuffer in einigen ObjectInputStream und lesen Sie die primitiven Werte von .readInt() erreicht werden könnte, halte ich es für eine chaotisch sein würde und langsam Abhilfe.

Also, gibt es andere Lösungen möglich ohne zu tun magischen Urtyp arithmetics (Verschiebung, die Überprüfung endians, ...)?

Hinweis: Ich brauche beiden Richtungen: byte [12] -> int [3] und int [3] -> byte [12]

War es hilfreich?

Lösung

Nach der Javadoc-, array () [1] gibt die Unterlage Arrays Puffer, ist das Array Sie mit dem Anruf zu wickeln angeben () [2].

Daher müssen Sie ein neues Array mit dem gewünschten Typ erstellen. Aber die arithmetics kann noch über die Pufferklassen behandelt werden.

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

rückwärts erfordert ein wenig Berechnung selbst.

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

Siehe auch:

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

[2]

Andere Tipps

Vielen Dank an wierob für seinen Code für die Umwandlung von byte [] -> int []

spielte ich ein wenig herum, um das entgegengesetzte Richtung zum Laufen zu bringen.

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

{
    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) Ausgang

[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]
scroll top