将LongBuffer/IntBuffer/ShortBuffer转换为ByteBuffer。

18
我知道一种快速的方法可以将字节数组/短整型数组/整型数组/长整型数组转换为ByteBuffer,然后获取字节数组。例如,要将字节数组转换为短整型数组,我可以这样做:
byte[] bArray = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };

ByteBuffer bb = ByteBuffer.wrap(byteArray);
ShortBuffer sb = bb.asShortBuffer();
short[] shortArray = new short[byteArray.length / 2];
sb.get(shortArray);

生成一个类似这样的短数组:[256, 0, 0, 0, 256, 0, 0, 0]我如何使用java.nio类进行逆操作? 现在我正在这样做:
shortArray[] = {256, 0, 0, 0, 256, 0, 0, 0};
ByteBuffer bb = ByteBuffer.allocate(shortArray.length * 2);
for (short s : shortArray) {
    bb.putShort(s);
}
return bb.array();

我获得了原始的[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]字节数组。但是我想使用类似ShortBuffer.asByteBuffer()的方法,而不是手动循环来实现。
我找到了一个2001年的向Sun提出的请求,但是他们没有接受它;-((

1
值得指出的是,在您提供的链接中,Oracle表示,如果没有直接ByteBuffer的支持,提供这样的“视图”仍然需要进行复制操作才能进行I/O写入。这就是他们不提供此方法的原因。 - Luciano
3个回答

33

这个怎么样?:

    bb.asShortBuffer().put(shortArray);

那么bb就包含了您的数据。

完整代码:

public class Test {
    public static void main(final String args[]) {
        short[] arr = { 256, 0, 0, 0, 256, 0, 0, 0 };
        for (byte b : F(arr)) {
            System.out.print(b);
        }
    }

    public static byte[] F(short[] arr) {
        java.nio.ByteBuffer bb = java.nio.ByteBuffer.allocate(arr.length * 2);
        bb.asShortBuffer().put(arr);
        return bb.array(); // this returns the "raw" array, it's shared and not copied!
    }
}

哇,这太聪明了! - Display Name
1
ByteBuffer.allocate(arr.length * 2) 将会分配 length*2 字节,因此该方法是在复制数据而不是将 short[] 强制转换为 byte[]。 - morpheus
@morpheus 这个问题是关于“转换”而不是“强制类型转换”的。 - A.H.
1
在Java中是否可以进行“强制转换”,即将short[]转换为byte[]而不需要额外的内存分配? - morpheus
目前我不知道有这样的机制。Buffer 是唯一可以让你在同一数据上获取 byteshort 视图的机制。但是普通数组不能像你想要的那样进行转换。 - A.H.

3

好的,在声明中

ShortBuffer sb = bb.asShortBuffer();

据我所知,你的ShortBuffer只是原始ByteBuffer的一个视图。因此,你可以随时访问原始的ByteBuffer变量bb,并通过你的CharBuffer引用sb查看修改后的数据。 asCharBuffer的文档表示:

[...] 此缓冲区内容的更改将在新缓冲区中可见,反之亦然[...]


@logoff ByteBuffer.wrap(sb.toString().getBytes()) 怎么样? - Edwin Dalorzo
1
它不起作用。结果是 [106, 97, 118, 97, 46, 110, 105, 111, 46, 72, 101, 97, 112, 83, 104, 111, 114, 116, 66, 117, 102, 102, 101, 114, 91, 112, 111, 115, 61, 48, 32, 108, 105, 109, 61, 56, 32, 99, 97, 112, 61, 56, 93]。这是因为 sb.toString() 返回 java.nio.HeapShortBuffer[pos=0 lim=8 cap=8] - logoff
3
即使那个方法有效,如果我们像这样篡改 toString 方法,使用 sb.toString().getBytes() 真的很丑陋。 - Pacerier

0

我会记得你用来创建ShortBuffer的ByteBuffer,因为它是对同一缓冲区的视图。

否则,似乎唯一的方法是使用反射来获取bb字段。

顺便说一句:根据你所做的事情,使用直接ByteBuffer可以显著提高速度,特别是如果你使用本机字节顺序。


使用直接的ByteBuffer速度更快,但是我之后无法访问其支持的数组。 - logoff
你用支持数组做什么? - Peter Lawrey
不是在我的代码片段中,但我最终需要它。无论如何,你的评论是正确的,但我需要这个数组,呵呵。 - logoff
我的观点是,通常你需要它用于诸如向文件或套接字写入数据之类的操作。如果使用NIO,可以避免将其转换为字节数组。 - Peter Lawrey
是的,没错。我正在做一些“奇怪的事情”,只是概念验证而已。无论如何,谢谢。 - logoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接