Java: Wie erstelle ich eine Methode für eine ganze Zahl von Split-Bits aus einem Byte-Array unter Verwendung einer Maske zu extrahieren

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

  •  02-10-2019
  •  | 
  •  

Frage

Während der Arbeit einiger Videos auf Decodierung Streaming-Standards Ich habe eine Menge von Fällen bemerkt, wo die Bits eines Integer-Wert in etwas 2 bis 6 Bytes zur Verfügung gestellt werden, sondern durch reservierte Bits getrennt ist, wie folgt:

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

Beispiel der Wert 185 (oder 10111001 0xB9) gespeichert werden würde, wie folgt in einem Zwei-Byte-Array:

01000110 00100100

Ich weiß, das ist verrückt, aber das ist die Art, wie diese Jungs ihren Datenstrom codiert haben. Es kann mit den folgenden Bit-Operationen extrahiert werden

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)

Was würde Ich mag die Lage sein, zu tun ist, ein Verfahren zu schaffen, das einen Byte-Array von unbestimmter Länge annehmen würde und eine Int eine Maske der Bits darstellt, die den Wert Constitué wir versuchen, aus der bereitgestellten Spezifikation abgeleitet zu extrahieren. So etwas wie diese

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

Ich habe das Projekt abgeschlossen Ich arbeite an den ursprünglichen „manuell“ Ansatz, aber ich bin nicht davon überzeugt, dass es so sauber ist, wie es durch die schiere Anzahl dieser Vorkommnisse und deren Komplexität sein könnte. Ich würde gerne mit einem allgemeineren Verfahren zu entwickeln, die das Gleiche erreichen könnten.

Leider bin ich immer noch ein Neuling, wenn es um diese Komplexität der Bitverschiebung kommt und ich hoffte, dass jemand ein paar Ratschläge oder Anregungen liefern könnte, wie dies am besten zu erreichen.

Xela

. Hinweis - Entschuldigen Syntaxfehler in dem Pseudo-Code über ihn nur als Erklärung für den Anwendungsfall zu dienen, entwerfen

War es hilfreich?

Lösung

Eigentlich neige ich dazu, zu denken, dass die Inline-Maske und Shift-Ansatz (wenn auch ein wenig sauberer als Ihr Pseudo-Code implementiert) ist besser als zu versuchen, eine Allzweck-Methode zu schreiben. Für einen erfahrenen Entwickler von Bit-Bashing Code Low-Level, Lesen masken und-Shift-Code sollte kein Problem sein. Das Problem mit einem Allzweck-Verfahren entlang der Linien, die Sie vorschlagen, ist, dass es deutlich sein wird weniger effizient ... und schwierig für die JIT-Compiler zu optimieren.

BTW, das ist, wie ich den Code schreiben würde.

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

Bearbeiten

Ich möchte immer noch zu verstehen, wie eine solche generischen Ansatz obwohl codiert werden könnten, als Lernübung.

So etwas wie folgt aus:

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

Wie Sie sehen können, das wird dauern bis zu 32 Schleifeniterationen Sie die Antwort zu geben. Für Ihr Beispiel, würde ich dieser Ansatz sagen ist etwa 10-mal langsamer als die ursprüngliche Version.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top