2014-08-29 1 views
4

ByteBuffer 두 개의 위치가 다른 버퍼의 하위 시퀀스라는 것을 알고있는 경우 ByteBuffer 개체가 다른 경우에 대해 상대적인 위치를 얻는 방법이 있습니까?원본 ByteBuffer에 상대적인 직접 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); 
} 

내가 직접 버퍼를 위해 무료로 존재하는 것도이 아니라고 생각 해요 :

내가이가 아닌 직접 배열 할 수 있다는 것을 알고 그래서 같은 arrayOffset() 방법을 사용하여 ByteBuffer을지지 . 비슷한 것을 얻으려면 내가 생각할 수있는 최상의 옵션은 ByteBuffer을 생성 한 버퍼 (부모 버퍼)에 대한 참조를 저장하고 부모의 0 위치에 대한 상대 위치를 기준으로 저장하는 것입니다.

EDIT : 어쨌든 ByteBuffer을 생성 할 수 없으므로 확장 할 수없는 것처럼 보입니다. 나는 래퍼 클래스의 일종을 대신 작성해야 할 것 같아요.

답변

1

리플렉션을 사용하여 가능합니다. 그러나 달성하고자하는 바에 따라 대안 솔루션을 고려해야합니다. 이 오프셋이 필요한 용도가 명확하지 않습니다. 은 "실용"추천

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

처럼, 간단한, 자신의 클래스로 버퍼를 랩이 하나의 작업을하는 것입니다,하지만이 사건에 적용 할 수 있는지 여부를 명확하지 않다.

여기 반사를 사용하여 코드를 게시하지만,

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

그래서 이것은 단지 데모는 것을 알게 될 것이다 :

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; 
    } 
} 
+0

반사 솔루션은 깔끔하지만 안전을 위해 내가 갈거야 생각 래퍼 라우트를 내려 가서'ByteBuffer'를'RelativeByteBuffer' 클래스에 캡슐화합니다. 불행히도'Buffer'는'duplicate()'와'slice()'메소드를 공개하지 않기 때문에'RelativeBuffer '처럼 깔끔한 일을 할 수 없습니다. – PaddyD

+0

오프셋은 버퍼에서 예기치 않은 데이터가 발견 된 경우 진단 로깅 용도로 사용됩니다. 버퍼가 생성 된 다른 버퍼를 기준으로 한 데이터 오프셋을 알아야합니다. – PaddyD

+0

전적으로 * 진단 목적을 위해 반사 용액이 좋다고 생각합니다. 그러한 분석을 수행하려는 의도가 클래스가 처음에 어떻게 모델링되는지에 영향을 미칠지는 확실하지 않습니다. 그러나 결국, 결정은 당신에게 달려 있습니다. 그리고 아마도 다른 사람이 글을 쓰고 답을하면 더 잘 맞는 것입니다. – Marco13

관련 문제