Java: Come faccio a creare un metodo per estrarre i bit dividere di un numero intero da un array di byte utilizzando una maschera

StackOverflow https://stackoverflow.com/questions/3176705

  •  02-10-2019
  •  | 
  •  

Domanda

Mentre si lavora su alcuni decodifica video in streaming standard Ho notato un sacco di casi in cui sono previsti i bit di un valore intero qualsiasi cosa, da 2-6 byte, ma separati da bit riservati nel seguente modo:

// 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

Per esempio, il valore 185 (10111001 o 0xB9) sarà memorizzato come seguito in una matrice di due byte:

01000110 00100100

So che questo è matto, ma questo è il modo in cui questi ragazzi hanno codificato il loro flusso di dati. Può essere estratto usando le operazioni bit seguente

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)

Nei vorrei essere in grado di fare è creare un metodo che accetta un array di byte di lunghezza indeterminata e un Int rappresenta una maschera di bit che costituiscono altrettanti il ??valore che si sta cercando di estratto derivato dalla specifica fornita. Qualcosa di simile a questo

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

Ho completato il progetto su cui stavo lavorando utilizzando l'approccio originale di "manuale", ma io non sono soddisfatto che sia pulita come potrebbe essere a causa del gran numero di questi eventi e la loro complessità. Mi piacerebbe venire con un metodo più generico che potrebbe ottenere la stessa cosa.

Purtroppo Sono ancora un principiante quando si tratta di questa complessità del bit spostamento e speravo che qualcuno potrebbe fornire qualche consiglio o suggerimenti sul modo migliore per raggiungere questo obiettivo.

Xela

Nota -. Scusa eventuali errori di sintassi nella pseudo-codice di cui sopra è progettare solo per servire come una spiegazione del caso d'uso

È stato utile?

Soluzione

In realtà, io tendo a pensare che la maschera in linea e l'approccio del cambio (se attuato un po 'più pulito di quanto il tuo pseudo) è meglio che cercare di scrivere un metodo di uso generale. Per uno sviluppatore esperto di codice di basso livello di bit colpisce, leggendo il codice maschera-e-shift dovrebbe essere un problema. Il problema con un metodo di uso generale, lungo le linee che proponiamo è che sarà molto meno efficienti ... e difficile per il compilatore JIT da ottimizzare.

A proposito, questo è il modo che avrei scritto il codice.

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

Modifica

  

mi piace ancora di capire come un approccio generico potrebbe essere codificato anche se, come un esercizio di apprendimento.

Qualcosa di simile a questo:

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

Come si può vedere, che si terrà fino a 32 iterazioni del ciclo di darvi la risposta. Per il vostro esempio, direi che questo approccio è circa 10 volte più lento rispetto alla versione originale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top