java bytebuffer slice 没有按照文档工作

Posted

技术标签:

【中文标题】java bytebuffer slice 没有按照文档工作【英文标题】:java bytebuffer slice not working as per documentation 【发布时间】:2017-04-07 08:37:21 【问题描述】:

我已经使用字节缓冲区很长时间了,但很少使用切片。但是现在我们在bytebuffer 上遇到了slice() 的大问题。

请看下面的代码:

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Arrays;

public class Test12 

    public static void main(String[] args) throws UnsupportedEncodingException 

        ByteBuffer original = ByteBuffer.wrap("234567".getBytes("UTF-8"));
        printBuffer("org: ",original);

        original.position(1);
        original.limit(original.limit()-2);

        printBuffer("org: ",original);


        ByteBuffer sliced =  original.slice();
        printBuffer("slc: ",sliced);

        ByteBuffer duplicated =  original.duplicate();
        printBuffer("dup: ",duplicated);

        ByteBuffer compact =  original.compact();
        printBuffer("cmp: ",compact); 
    


    private static  void printBuffer(String prefix,ByteBuffer buff) 
    
        System.out.println(prefix+buff);
        System.out.println(prefix+Arrays.toString(Arrays.copyOfRange(buff.array(), buff.position(), buff.limit())));

    


结果

org: java.nio.HeapByteBuffer[pos=0 lim=6 cap=6]
org: [50, 51, 52, 53, 54, 55]
org: java.nio.HeapByteBuffer[pos=1 lim=4 cap=6]
org: [51, 52, 53]
slc: java.nio.HeapByteBuffer[pos=0 lim=3 cap=3]
slc: [50, 51, 52]
dup: java.nio.HeapByteBuffer[pos=1 lim=4 cap=6]
dup: [51, 52, 53]
cmp: java.nio.HeapByteBuffer[pos=3 lim=6 cap=6]
cmp: [53, 54, 55]

请查看上述结果中的 slc: 值。我期待像[51, 52, 53] 这样的东西。

如果我错了,请纠正我。 是java中的Bug吗?

我在 java 7 , 8 中对此进行了测试

【问题讨论】:

【参考方案1】:

要添加到 m.antkowicz 答案,该位置确实是 0,但感谢切片的 offset 属性(您可以使用 buff.arrayOffset() 访问),使用:

sliced.get(0);

会给你51。要打印可视化,请将您的 printBuffer 方法更改为:

private static void printBuffer(String prefix, ByteBuffer buff) 
    System.out.println(prefix + buff);
    System.out.print(prefix);
    for (int i = buff.position(); i < buff.limit(); i++) 
        System.out.print(" " + buff.get(i));
    
    System.out.println();

它将打印:

org: java.nio.HeapByteBuffer[pos=0 lim=6 cap=6]
org:  50 51 52 53 54 55
org: java.nio.HeapByteBuffer[pos=1 lim=4 cap=6]
org:  51 52 53
slc: java.nio.HeapByteBuffer[pos=0 lim=3 cap=3]
slc:  51 52 53
dup: java.nio.HeapByteBuffer[pos=1 lim=4 cap=6]
dup:  51 52 53
cmp: java.nio.HeapByteBuffer[pos=3 lim=6 cap=6]
cmp:  53 54 55

要继续使用Arrays.asList,请将offset 添加到positionlimit 属性中:

int offset = buff.arrayOffset();
Arrays.copyOfRange(buff.array(), buff.position() + offset, buff.limit() + offset)

回想一下,在后台,slice 与原始缓冲区共享相同的底层数组。仅更改了offset 属性,以便您可以使用不同的位置访问缓冲区的子部分。

【讨论】:

谢谢 Evryone。我现在明白了。【参考方案2】:

来自slice方法reference:

新缓冲区的位置将为零,其容量和限制将是此缓冲区中剩余的字节数,其标记将未定义。

因此,尽管您将位置设置为 1,但由于文档原因它可以正常工作

【讨论】:

“新缓冲区的内容将从这个缓冲区的当前位置开始”怎么样?【参考方案3】:

您的 printBuffer 方法错误:slice 在内部创建了一个偏移量以访问底层字节数组。

要从底层字节数组中输出正确的值,printBuffer 方法也需要使用这个偏移量:

private static  void printBuffer(String prefix,ByteBuffer buff) 

    System.out.println(prefix+buff);
    System.out.println(prefix+Arrays.toString(Arrays.copyOfRange(buff.array(), buff.position()+buff.arrayOffset(), buff.limit()+buff.arrayOffset())));


【讨论】:

以上是关于java bytebuffer slice 没有按照文档工作的主要内容,如果未能解决你的问题,请参考以下文章

我如何使用Mockito来验证带有ByteBuffer参数的调用?

Java Bytebuffer 只能顺序读取?

Java:从 ByteBuffer 扩展

ByteBuffer 可以实现 DataOutput/DataInput 吗?

基于类似于来自java的ByteBuffer的字节集合

JNA/ByteBuffer 没有被释放并导致 C 堆内存不足