我正在使用Python construct解析器处理一些二进制数据,但我没有按照预期的方式获取字符串。
请注意,在下面的简化示例中,我可以使用unpack或甚至只是一个切片,但我正在解析的实际数据不能完全对齐到字节边界。
一些示例代码:
from construct import BitStruct, BitField, Padding, String
struct = BitStruct("foo",
BitField("bar", 8),
BitField("baz", 16),
Padding(4),
BitField("bat", 4)
)
struct2 = BitStruct("foo",
BitField("bar", 8),
String("baz", 16),
Padding(4),
BitField("bat", 4)
)
data = "\x01AB\xCD"
print struct.parse(data)
print struct2.parse(data)
打印输出:
Container:
bar = 1
baz = 16706
bat = 13
Container:
bar = 1
baz = '\x00\x01\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x01\x00'
bat = 13
我原以为String会将AB
作为实际字符串返回给我。但是它会返回等效的二进制字符串。
如何说服构造返回实际的ASCII字符串?
答案 0 :(得分:1)
我通过创建Adapter解决了这个问题。原始ASCII值被解析为整数列表,然后可以将其转换为字符串表示形式。
这不是最优雅的方式,但由于BitStruct仅在位值上运行,因此它似乎是最简单的解决方法。改进版本将解析不同长度的字符串(例如7位ASCII)。
from binascii import hexlify
from construct import BitStruct, BitField, Padding, Array, Octet, Adapter
class BitStringAdapter(Adapter):
def _encode(self, obj, context):
return list(ord(b) for b in obj)
def _decode(self, obj, context):
return "".join(chr(b) for b in obj)
struct = BitStruct("foo",
BitField("bar", 8),
BitStringAdapter(Array(2, Octet("baz"))),
Padding(4),
BitField("bat", 4)
)
data = "\x01AB\xCD"
out = struct.parse(data)
print hexlify(struct.build(out))
输出:
Container:
bar = 1
baz = 16706
bat = 13
0141420d
哪个是正确的 - C
字节被丢弃,因为它被标记为填充,这很好。
答案 1 :(得分:0)
python模块bitstruct也可用于解析位字段。它使用格式字符串,就像标准库结构模块一样。
格式说明符't'用于文本。
>>> from bitstruct import unpack
>>> data = b'\x01AB\xCD'
>>> unpack("u8u16p4u4", data)
(1, 16706, 13)
>>> unpack("u8t16p4u4", data)
(1, u'AB', 13)