2016-11-14 125 views
1

我试图解码一个假定的十六进制字符串。在MS SQL Server(11.0.2100)中,数据的类型为char(8)将十六进制字符串解码为4个映射到值的二进制映射的片段

在手册中有对数据进行解码的没有明确的方式,但它记录了它所包含的内容:

给出一个十六进制字符串即。 0001003F,长度为4.低位字节 位于右侧,高位字节位于左侧。对于4个 'bytes',给出了将“比特”映射到某个真值的参考表。也给出了位顺序是有在最右边的是第1位的位0或位 ,......等等

表看起来是这样的:

一号“字节”:

|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个更多的表如下未来3其他“字节的...,每个4”字节的理应有‘位’的8个相等的数)

我认为该数据进行解码的方式是分割十六进制字符串int O 4份,并将其转换成一个二进制串宽度固定与8.

PHP,所采取的示例十六进制“0001003F”,第一个字节是“3F”,具有转换为二进制,0011 1111(空间明晰)。然后,推断第一个字节的值为:

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

我也试过:hex2bin("0001003F"),但它输出strin(4) " # "

这是解码这些数据的正确方法吗?

(对不起,如果标签是不正确的。)

回答

1

由于4个字节融入储存integer type在几乎所有平台(32位及更高版本),你可以转换十六进制字符串整数,然后使用bitwise operators来检查是否存在特定的位被置位:

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

输出

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 

如果位$bit设置为(1),则该位对应的状态为,位于

base_convert函数的帮助下,代码将十六进制字符串$hex_str转换为整数$flags。循环迭代[0;31]范围内的位数(从最低有效位开始)。 (1 << $bit)表达式是1的值向左移位01​​位。因此,如果位号$bit被设置,则按位运算的结果是非零整数。如果结果不为零,结果将转换为boolean类型以生成1,否则返回0

这是很容易看到,你可以测试的比特数与单按位操作,例如:

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

输出

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

我的解决方案是非常相似你的答案。这种编码/解码在实践中是否存在?我对这种编码/解码方案并不熟悉。 –

+0

@ javiniar.leonard,这取决于问题。特别是,我不认为'CHAR(8)'是一个掩码的好选择。如果知道位数不会超过64,那么我宁愿使用'BIGINT'。如果状态的属性可能会增长,或者状态将来可能与其他表有关系,我将为状态创建一个表,并为对象状态创建一个表,如'obj_states(object_id,state_id)'。但是,一些DBMS实现可能会在'BINARY'字段(MySQL 8.0的计划扩展)上按位操作。 –

+1

但是,您显然通过以代码复杂性的价格存储十六进制字符来节省一些空间。您可以使用'BINARY'字段更好地压缩它们; 'HEX(bin_field)'可以返回十六进制字符串以便在PHP中进一步处理。 –

相关问题