2016-11-14 3 views
1

Ich versuche, eine vermeintlich hexadezimale Zeichenkette zu dekodieren. In MS SQL Server (11.0.2100) haben die Daten den Typ char(8).Eine Hex-Zeichenkette in 4 Teile dekodieren, die auf eine binäre Werte-Map

In den Handbüchern gab es keinen klaren Weg, um die Daten der Decodierung aber es dokumentiert, was es enthält:

einen Hex-String also gegeben. 0001003F mit einer Länge von 4. Das untere Byte ist auf der rechten Seite, das höhere Byte ist auf der linken Seite. Für jeden der 4 'bytes' wurde eine Referenztabelle angegeben, die ein 'Bit' auf einen bestimmten truthy Wert abbildet. Ein bisschen Ordnung wird auch das Bit 0 oder das Bit in ganz rechts gegeben, die die erste Bit ist, ... usw.

Die Tabelle sieht wie folgt aus:

1. 'byte':

|Bit Order | Description | 1    | 0    | trigger  | 
|-----------|---------------|-------------------|-------------------|---------------| 
|BIT0  | state foo  | state foo is ON | State foo is OFF | high level | 
|BIT1  | state bar  | in state bar  | not in state bar | high level | 
|         ... 
|BIT7  | state bazz | in state bazz  | not in state bazz | high level | 

(3 weitere Tabellen folgen für die nächste drei andere ‚Byte ist ..., die jeweils der 4‘ Byte angeblich das hat 8 die gleiche Anzahl von ‚Bits‘)

ich dachte, die Möglichkeit, diese Daten zur Decodierung ist die hexadezimale Zeichenfolge int o 4 Teile und wandeln sie in ein Binärstring Breite mit einem festen von 8.

In PHP das Beispiel hex genommen ‚0001003F‘, das erste Byte war ‚3F‘, auf das umgewandelte binäre haben, 0011 1111 (Platz für Klarheit). Dann folgerte, dass der Wert für das erste Byte war:

'state foo is on', 'in state bar', ..., 'not in state bazz'.

Ich habe auch versucht zu tun: hex2bin("0001003F") aber es gibt strin(4) " # " aus.

Ist das die korrekte Dekodierung dieser Daten?

(Ich bitte um Verzeihung, wenn die Tags nicht korrekt sind.)

Antwort

1

Seit 4 Bytes in den Speicher passen für integer type auf fast allen Plattformen (32-Bit und höher), können Sie die Hex-String konvertieren integer, dann mit dem bitwise operators überprüfen, ob bestimmte Bit gesetzt ist:

$hex_str = '0001003F'; 
$flags = base_convert($hex_str, 16, 10); 

foreach (range(0, 31) as $bit) { 
    printf("Bit %d: %d\n", $bit, (bool) ($flags & (1 << $bit))); 
} 

Output

Bit 0: 1 
Bit 1: 1 
Bit 2: 1 
Bit 3: 1 
Bit 4: 1 
Bit 5: 1 
Bit 6: 0 
... 
Bit 15: 0 
Bit 16: 1 
Bit 17: 0 
... 
Bit 31: 0 

Wenn Bit $bit gesetzt ist (1), dann ist der diesem Bit entsprechende Zustand unter.

Der Code konvertiert die Hex-Zeichenfolge $hex_str in eine Ganzzahl $flags mit Hilfe von base_convert Funktion. Die Schleife iteriert Bitnummern im Bereich [0;31] (beginnend mit dem niedrigstwertigen Bit). Der Ausdruck (1 << $bit) ist der Wert 1, der um $bit Bits nach links verschoben ist.Wenn also die Bitnummer $bit gesetzt ist, ist das Ergebnis der bitweisen Operation UND eine ganze Zahl ungleich null. Das Ergebnis wird in boolean umgewandelt, um 1 zu erzeugen, wenn das Ergebnis nicht Null ist, und andernfalls 0.

Es ist leicht zu sehen, dass Sie eine Anzahl von Bits mit einem einzigen bitweise UND Betrieb testen, zum Beispiel:

// Check if at least one of three bits is set, 3rd, 10th, or 11th 
$mask = (1 << 3) | (1 << 10) | (1 << 11); 
if ($flags & $mask) 
    printf("At least one of the bits from mask 0x%x is set\n", $mask); 

Ausgabe

At least one of the bits from mask 0xc08 is set 
+0

Meine Lösung recht ähnlich war Deine Antwort. Gibt es diese Art der Kodierung/Dekodierung in der Praxis? Dieses Codier-/Decodierschema ist mir wirklich nicht vertraut. –

+0

@ javiniar.leonard, es hängt von dem Problem ab. Insbesondere glaube ich nicht, dass 'CHAR (8)' eine gute Wahl für eine Bitmaske ist. Wenn sicher ist, dass die Anzahl der Bits nicht größer als 64 ist, würde ich lieber "BIGINT" verwenden. Wenn die Eigenschaften der Zustände wahrscheinlich wachsen oder die Zustände in Zukunft Beziehungen zu anderen Tabellen haben, würde ich eine Tabelle für die Zustände und eine Tabelle für Objektzustände wie 'obj_states (object_id, state_id)' erstellen. Einige DBMS-Implementierungen können jedoch bitweise Operationen in 'BINARY'-Feldern enthalten (eine geplante Erweiterung für MySQL 8.0). –

+1

Aber Sie sparen natürlich etwas Platz, indem Sie die Hexadezimalzeichen zum Preis der Codekomplexität speichern. Sie könnten sie mit einem 'BINARY'-Feld besser komprimieren; 'HEX (bin_field)' könnte die hexadezimale Zeichenfolge zur weiteren Verarbeitung in PHP zurückgeben. –

Verwandte Themen