爪哇:在原始数组上使用类型双关?
-
20-09-2019 - |
题
我需要能够将字节数组与其他原始类型数组相互转换,但我需要而不是强制转换 类型双关语. 未经铸造的原始副本的正确术语是什么?
我认为可以执行以下操作:
// 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()
是 不是 通过“按位”或“原始”复制内容来创建新的 IntBuffer,但在现有 ByteBuffer 上创建新的“视图”。这就是为什么 .array()
是为了失败。
我浏览了 JDK 的源代码,发现了一些类,这些类被所有这些缓冲类和 会 做我需要的东西,但是是内部的(例如类 Unsafe
).
虽然我认为我的目标可以通过将字节缓冲区包装在一些 ObjectInputStream
并通过以下方式读取原始值 .readInt()
, ,我认为这将是一个混乱且缓慢的解决方法。
那么,还有其他可能的解决方案吗 没有 进行神奇的原始类型算术(移位、检查字节序……)?
笔记:我需要两个方向:byte[12] -> int[3] 和 int[3] -> byte[12]
解决方案
根据 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
其他提示
非常感谢 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]