2010-07-05 1 views
1

일부 비디오 스트리밍 표준을 디코딩하는 동안 Integer 값 비트가 제공되는 많은 인스턴스를 발견했습니다.Java : 마스크를 사용하여 바이트 배열에서 Integer의 분할 비트를 추출하는 방법을 만드는 방법

01000110 00100100 

: 두 바이트 어레이로 다음과 같이

// Specification (16 bits) 
// ----------------------- 
// Reserved   1 bit 
// Value A [6-7] 2 bit 
// Reserved   2 bit 
// Value A [4-5] 2 bit 
// Reserved   3 bit 
// Value A [0-3] 4 bit 
// Reserved   2 bit 

는, 예를 들면 값 (185) (10111001 또는 0xB9)에 저장 될 것이다 : 다음 2-6 바이트로하지만, 예비 비트에 의해 분리 나는 이것이 너트라고 알고 있지만 이것은 w이다. 이 사람들은 데이터 스트림을 코딩했습니다. I 할 수 싶은 것이 다음 비트 연산

int w = 0; 
w |= (0x60 & data[0]) >>> 5; // extract the first 2 bits shifted to the front 
w <<= 2;      // bump them up 2 bits for the next section 
w |= (0x06 & data[0]) >>> 1; // extract the next 2 bits shifted to the front 
w <<= 4;      // bump them up 4 bits for the last section 
w |= (0x3C & data[0]) >>> 2; // extract the last 4 bits shifted to the front 

// w now will equal 10111001 (185) 

를 사용하여 추출 될 수있는 것은이 constitue 비트의 마스크를 나타내는 미결정 길이의 바이트 배열 int를 받아들이는 방법을 생성하는 것이다 제공된 사양에서 파생 된 추출하려는 값. 내가 원래 "수동"접근 방식을 사용하여 작업 한 프로젝트를 완료,하지만 난 때문에이 사건의 깎아 지른듯한 숫자로하고, 모든 경우에 적용 할 수있는 깨끗한 지하지 만족이

public static void testMethod() { 

    byte[] data = new byte[] {0x46, 0x24}; // 01000110 00100100 
    int mask = 0x663C;      // 01100110 00111100 
    int x = readIntFromMaskedBytes(data, mask); 

} 

public static int readIntFromMaskedBytes(byte[] data, int mask) { 
    int result = 0; 

    // use the mask to extract the marks bits from each 
    // byte and shift them appropriately to form an int 

    return result; 
} 

같은 뭔가 그들의 복잡성. 나는 똑같은 것을 성취 할 수있는보다 일반적인 방법을 생각해 내고 싶다.

불행히도 저는 비트 이동의 복잡성에 관해서는 여전히 초보자입니다. 누군가가 이것을 성취하는 방법에 대한 조언이나 제안을 줄 수 있기를 희망했습니다.

Xela에

주 -이 사용 사례에 대한 설명이 될 수있는 유일한 디자인은 위의 의사 코드에 구문 오류 실례합니다.

+0

왜 'byte []'의 길이가 정해지지 않습니까? 예를 들어 '.length = 100'? 'int' 마스크의 경우 최대 4 개로 제한하고 싶지 않습니까? – polygenelubricants

+0

물론 이것은 언급 한 바와 같이 의사 코드 일 뿐이며 최종 구현을 반영하지 않습니다. int 및 long 기반 변형이 적용되고 입력이 예상 된 바이트 길이 내에 있는지 확인하기 위해 입력이 게이트 처리됩니다. – Xela

답변

1

실제로 필자는 인라인 마스크 및 시프트 방식 (일반 의사 코드보다 조금 더 구현 된 경우)이 범용 메서드를 작성하는 것보다 낫다고 생각하는 경향이 있습니다. 숙련 된 저수준 비트 배싱 코드 개발자는 마스크 및 시프트 코드 읽기가 문제가되지 않아야합니다. 제안하는 라인에 따른 범용 메소드의 문제점은 JIT 컴파일러가 최적화하는 것이 효율적이지 않으며 ... 어렵다는 것입니다.

나는이 코드를 작성합니다.

// extract and assemble xxxx from yyyy 
int w = ((0x003C & data[0]) >> 2) | 
     ((0x0600 & data[0]) >> 6) | 
     ((0x6000 & data[0]) >> 7); 

편집

나는 여전히 일반적인 접근 방식은 학습 운동으로,하지만 코딩 할 수있는 방법을 이해하고 싶습니다. 이 같은

뭔가 : 당신이 볼 수 있듯이

public static int readIntFromMaskedBytes(int data, int mask) { 
    int result = 0; 
    int shift = 0; 
    while (mask != 0) { 
     if (mask & 1) { 
      result |= (data & 1) << shift++; 
     } 
     data >>>= 1; 
     mask >>>= 1; 
    } 
} 

, 즉 32 루프 반복이 소요됩니다 당신에게 대답을 줄 수 있습니다. 귀하의 예를 들어, 나는이 접근 방식이 원래 버전보다 약 10 배 느린 것이라고 말하고 싶습니다.

+0

답장을 보내 주셔서 감사합니다. 스티븐, 귀하의 의견을 확실히 고려하겠습니다. 나는 아직도 그러한 일반적인 접근법이 어떻게 학습 할 수 있는지를 이해하고 싶다. – Xela

+0

뛰어난. 아침에이 문제를 해결하겠습니다.하지만 제안대로 프로덕션 코드에서 직접 접근 방식을 계속 사용합니다. 귀하의 조언을 주셔서 감사합니다 스티븐. – Xela