简体   繁体   English

获取相对于原始ByteBuffer的直接ByteBuffer切片位置

[英]Get direct ByteBuffer slice position relative to original ByteBuffer

Is there any way of getting a direct ByteBuffer zero position relative to another, given only the two ByteBuffer objects, if it is known that it is a subsequence of the other buffer? 如果知道它是另一个缓冲区的子序列,是否有任何方法可以获得相对于另一个的直接ByteBuffer零位置,只给出两个ByteBuffer对象?

I know that this can be done with a non-direct array backed ByteBuffer using the arrayOffset() method like so: 我知道这可以通过使用arrayOffset()方法的非直接数组支持的ByteBuffer来完成,如下所示:

int getRelativeBufferOffset(ByteBuffer parentBuffer, ByteBuffer childBuffer)
{
  return childBuffer.arrayOffset() - parentBuffer.arrayOffset();
}

void example()
{
  ByteBuffer buffer1 = ByteBuffer.allocate(10000);
  buffer1 .position(22);
  ByteBuffer buffer2 = buffer1.slice();
  buffer2.position(55);
  ByteBuffer buffer3 = buffer2.slice();

  // returns 22
  getRelativeBufferOffset(buffer1, buffer2);

  // returns 55
  getRelativeBufferOffset(buffer2, buffer3);

  // returns 77
  getRelativeBufferOffset(buffer1, buffer3);
}

I'm thinking that there isn't anything that exists for free for direct buffers. 我认为直接缓冲区没有任何免费存在的东西。 In order to get something similar the best option I can think of is to extend ByteBuffer to store a reference to the buffer from which it was created (the parent buffer) and the zero position relative to the parent's zero position at which it was created. 为了得到类似的东西,我能想到的最好的选择是扩展ByteBuffer来存储对创建它的缓冲区的引用(父缓冲区)和相对于父元素创建它的零位置的零位置。

EDIT: Annoyingly it looks like I can't extend ByteBuffer because none of its constructors are visible. 编辑:令人讨厌的是,我看起来无法扩展ByteBuffer因为它的构造函数都不可见。 I guess I will have to write some kind of wrapper class instead. 我想我将不得不写一些包装类。

It is possible, using reflection. 使用反射是可能的。 But depending on what you want to achieve, you should consider alternative solutions. 但是,根据您想要实现的目标,您应该考虑替代解决方案。 It's not clear for which purpose you need this offset. 目前尚不清楚您需要这种偏移的目的。 The "pragmatic" recommendation would be to wrap the buffers into a simple, own class, like “务实”的建议是将缓冲区包装成一个简单的,自己的类,如

class SlicedBuffer {
    int getBuffer() { ... }
    Buffer getParent() { ... }
    int getOffsetToParent() { ... }
}

and work with this one, but it's not clear whether this is applicable in your case. 并与此合作,但目前尚不清楚这是否适用于您的情况。

I'll post the code using reflection here, but note that 我将在这里使用反射发布代码,但请注意

// Many things...
// ... can go ...
// ... wrong when...
// ... using reflection

so this is only a demonstration: 所以这只是一个示范:

import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;

public class DirectByteBufferSliceOffsetsTest
{
    public static void main(String[] args)
    {
        testArray();
        testDirect();
    }

    private static void testArray()
    {
        System.out.println("Array: ");

        ByteBuffer buffer1 = ByteBuffer.allocate(10000);
        buffer1.position(22);
        ByteBuffer buffer2 = buffer1.slice();
        buffer2.position(55);
        ByteBuffer buffer3 = buffer2.slice();

        // prints 22
        System.out.println(getRelativeBufferOffsetArray(buffer1, buffer2));

        // prints 55
        System.out.println(getRelativeBufferOffsetArray(buffer2, buffer3));

        // prints 77
        System.out.println(getRelativeBufferOffsetArray(buffer1, buffer3));
    }

    private static int getRelativeBufferOffsetArray(
        ByteBuffer parentBuffer, ByteBuffer childBuffer)
    {
        return childBuffer.arrayOffset() - parentBuffer.arrayOffset();
    }


    private static void testDirect()
    {
        System.out.println("Direct: ");

        ByteBuffer buffer1 = ByteBuffer.allocateDirect(10000);
        buffer1.position(22);
        ByteBuffer buffer2 = buffer1.slice();
        buffer2.position(55);
        ByteBuffer buffer3 = buffer2.slice();

        // prints 22
        System.out.println(getRelativeBufferOffsetDirect(buffer1, buffer2));

        // prints 55
        System.out.println(getRelativeBufferOffsetDirect(buffer2, buffer3));

        // prints 77
        System.out.println(getRelativeBufferOffsetDirect(buffer1, buffer3));
    }

    private static int getRelativeBufferOffsetDirect(
        ByteBuffer parentBuffer, ByteBuffer childBuffer)
    {
        long parentAddress = getAddress(parentBuffer);
        long childAddress = getAddress(childBuffer);
        int offset = (int)(childAddress - parentAddress);
        return offset;
    }

    private static long getAddress(Buffer buffer)
    {
        Field f = null;
        try
        {
            f = Buffer.class.getDeclaredField("address");
            f.setAccessible(true);
            return f.getLong(buffer);
        }
        catch (NoSuchFieldException e)
        {
            // Many things...
            e.printStackTrace();
        }
        catch (SecurityException e)
        {
            // ... can go ...
            e.printStackTrace();
        }
        catch (IllegalArgumentException e)
        {
            // ... wrong when...
            e.printStackTrace();
        }
        catch (IllegalAccessException e)
        {
            // ... using reflection
            e.printStackTrace();
        }
        finally
        {
            if (f != null)
            {
                f.setAccessible(false);
            }
        }
        return 0;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM