1

我正在尝试解码一个所谓的十六进制字符串。在MS SQL Server (11.0.2100)中,数据的类型为char(8).

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

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

该表如下所示:

第一个“字节”:

|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 个相等数量的“位”)

我认为解码这些数据的方法是将十六进制字符串分成 4 部分并将它们转换为二进制字符串,宽度固定为 8。

PHP中,以十六进制 ' 0001003F' 为例,第一个字节是 ' 3F',已转换为二进制,0011 1111(为清楚起见有空格)。然后,推断出第一个字节的值是:

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

我也尝试过这样做:hex2bin("0001003F")但它输出strin(4) " # ".

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

(如果标签不正确,请见谅。)

4

1 回答 1

1

由于几乎所有平台(32 位及更高位)上整数类型的存储都适合 4 个字节,因此您可以将十六进制字符串转换为整数,然后使用按位运算符检查是否设置了特定位:

$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),则对应于该位的状态为on

该代码借助函数将十六进制字符串转换$hex_str为整数。循环迭代范围内的位数(从最低有效位开始)。表达式是左移位的值。因此,如果设置了位数,则按位运算的结果是一个非零整数。如果结果非零,则将结果转换为布尔类型以产生,否则。$flagsbase_convert[0;31](1 << $bit)1$bit$bit10

很容易看出,您可以使用单个按位运算来测试多个位,例如:

// 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
于 2016-11-14T04:03:13.780 回答