Java:在原始数组上使用类型双关?

发布于 2024-08-21 13:38:23 字数 1079 浏览 9 评论 0原文

我需要能够在字节数组与其他原始类型数组之间进行转换,但我需要 类型双关不进行强制转换的原始副本的正确术语?

我认为可以执行以下操作:

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

不幸的是,似乎 bb.asIntBuffer()不是.array() 注定会失败的原因。

我浏览了 JDK 的源代码,发现很少有类,它们被所有这些缓冲区类使用,并且做我需要的事情,但是是内部的(例如类Unsafe)。

虽然我认为我的目标可以通过将字节缓冲区包装在一些 ObjectInputStream 中并通过 .readInt() 读取原始值来实现,但我认为这将是一个混乱且混乱的过程。缓慢的解决方法。

那么,是否有任何其他可能的解决方案而不进行神奇的原始类型算术(移位、检查字节序……)?

注意:我需要两个方向:byte[12] -> int[3] 和 int[3] ->字节[12]

I need to be able to convert byte arrays to/from other primitive type arrays, but instead of casting, I need type punning. Correct term for raw copy without casting?

I thought it would be possible to do the following:

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

Unfortunately, it seems that bb.asIntBuffer() is not creating a new IntBuffer by copying the content "bitwise" or "raw", but creates a new "view" on existing ByteBuffer. That's why .array() is intended to fail.

I browsed around in JDK's sources, and found few classes, which are used by all these buffer classes and would do the stuff I need, but are internal (such as the class Unsafe).

While I think that my goal could be achieved by wrapping the byte buffer in some ObjectInputStream and read the primitive values by .readInt(), I think it would be a messy and slow workaround.

So, are there any other solutions possible without doing magical primitive type arithmetics (shifting, checking endians, ...)?

NOTE: I need both directions: byte[12] -> int[3], and int[3] -> byte[12]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

污味仙女 2024-08-28 13:38:23

根据 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

According to the javadoc, array() [1] returns the buffer's backing array which is the array you specify with the call to wrap() [2].

Hence, you must create a new array with the desired type. But the arithmetics can still be handled via the Buffer classes.

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

Backwards requires a little bit of calculation by yourself.

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

余生一个溪 2024-08-28 13:38:23

非常感谢 wierob 提供的转换 byte[]->int[] 的代码!

我尝试了一下,让相反的方向工作。

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]

Many thanks to wierob for his code for converting byte[]->int[] !

I played around a bit to get the opposite direction working.

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) Test case

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

[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]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文