Java: Comment puis-je créer une méthode pour extraire un des bits de division de nombres entiers à partir d'un tableau d'octets en utilisant un masque

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

  •  02-10-2019
  •  | 
  •  

Question

Tout en travaillant sur le décodage certaines normes streaming vidéo je l'ai remarqué beaucoup de cas où les bits d'une valeur entière sont fournis dans quelque chose de 2-6 octets, mais séparés par des bits réservés, comme suit:

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

Par exemple, la valeur 185 (ou 10111001 0xB9) sera stockée de la façon suivante dans un tableau à deux octets:

01000110 00100100

Je sais que cela noix, mais c'est la façon dont ces gars-là ont codé leur flux de données. Il peut être extrait à l'aide des opérations de bit suivant

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)

Ce que je voudrais être en mesure de faire est de créer une méthode qui accepte un tableau d'octets d'une durée indéterminée et un Int représentant un masque des bits qui Constitué la valeur que nous essayons d'extrait dérivé de la spécification fournie. Quelque chose comme ceci

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

J'ai terminé le projet que je travaillais sur l'utilisation de l'approche « manuel » d'origine, mais je ne suis pas convaincu qu'il est aussi propre que cela pourrait être dû au grand nombre de ces événements et de leur complexité. J'aimerais trouver une méthode plus générique qui pourrait faire la même chose.

Malheureusement, je suis encore un débutant en ce qui concerne cette complexité de décalage de bits et j'espérais que quelqu'un pourrait fournir des conseils ou des suggestions sur la meilleure façon d'y parvenir.

Xela

Remarque -. Excusez toute erreur de syntaxe dans le pseudo-code ci-dessus, il est la conception que pour servir d'explication de cas d'utilisation

Était-ce utile?

La solution

En fait, je tends à penser que l'approche masque en ligne et le déplacement (si elles sont appliquées un peu plus propre que votre pseudo-code) est mieux que d'essayer d'écrire une méthode d'usage général. Pour un développeur expérimenté de bit de code bas niveau dénigrement, lecture de code masque et changement devrait poser aucun problème. Le problème avec une méthode d'usage général le long des lignes que vous proposez est que ce sera beaucoup moins efficace ... et difficile pour le compilateur JIT pour optimiser.

BTW, voici comment j'écrire le code.

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

EDIT

  

Je voudrais encore comprendre comment une telle approche générique pourrait être codé si, comme un exercice d'apprentissage.

Quelque chose comme ceci:

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

Comme vous pouvez le voir, cela prendra jusqu'à 32 itérations de la boucle pour vous donner la réponse. Pour votre exemple, je dirais que cette approche est à peu près 10 fois plus lent que la version originale.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top