4

バイト配列を他のプリミティブ型配列との間で変換できるようにする必要がありますが、キャストする代わりに、型の punningが必要です。キャストなしの生のコピーの正しい用語は?

次のことができると思いました。

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

残念ながら、コンテンツを「ビットごと」または「生」にコピーして新しい IntBuffer を作成するのでbb.asIntBuffer()なく、既存の ByteBuffer に新しい「ビュー」を作成するようです。だからこそ.array()、失敗することが意図されています。

JDKのソースをブラウズしたところ、これらすべてのバッファクラスで使用され、必要なことを実行するクラスがほとんど見つかりませんでしたが、内部です( class などUnsafe)。

ObjectInputStreamバイトバッファをラップしてプリミティブ値を読み取ることで目標を達成できると.readInt()思いますが、面倒で遅い回避策になると思います。

それで、魔法のプリミティブ型の算術演算(シフト、エンディアンのチェックなど)を行わずに可能な他の解決策はありますか?

注: 両方向が必要です: byte[12] -> int[3]、および int[3] -> byte[12]

4

2 に答える 2

6

javadocによると、array()[1]は、wrap()[2]の呼び出しで指定した配列であるバッファのバッキング配列を返します。

したがって、目的のタイプで新しい配列を作成する必要があります。ただし、算術演算は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);

逆方向には、自分で少し計算する必要があります。

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

見る:

[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

于 2010-02-13T08:11:36.960 に答える
1

byte[]->int[] を変換するためのコードを提供してくれたwierobに感謝します。

私は少し遊んで、反対方向が機能するようにしました。

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) テストケース

{
    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) アウトプット

[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]
于 2010-02-13T09:26:45.240 に答える