dop*_*ish 21 binary parsing protocols
所以,我得到了这些数据.从网络套接字,或从文件中.我正在拼凑将解释数据的代码.读取一些字节,检查一些标志,一些字节表示后面有多少数据.读入那么多数据,冲洗,重复.
这个任务让我想起解析源代码.我对lex/yacc和antlr很满意,但他们不能胜任这项任务.你不能将比特和原始字节指定为标记(好吧,也许你可以,但我不知道如何),你不能把它们哄成"读取两个字节,使它们成为无符号的16位整数,称之为n,然后读取n个字节."
然后,当以系统方式定义协议/数据格式的规范(并非所有规范都是)时,应该有一种系统的方式来读取根据协议格式化的数据.对?
必须有一个工具来做到这一点.
dpm*_*min 10
最近出现了Kaitai Struct计划来完全解决这个问题:从规范中生成二进制解析器.您可以提供一种方案,以基于YAML/JSON的格式序列化任意数据结构,如下所示:
meta:
id: my_struct
endian: le
seq:
- id: some_int
type: u4
- id: some_string
type: str
encoding: UTF-8
size: some_int + 4
- id: another_int
type: u4
Run Code Online (Sandbox Code Playgroud)
使用ksc它们编译它们(它们提供了一个参考编译器实现),并且,瞧,你有一个任何支持的编程语言的解析器,例如,在C++中:
my_struct_t::my_struct_t(kaitai::kstream *p_io, kaitai::kstruct *p_parent, my_struct_t *p_root) : kaitai::kstruct(p_io) {
m__parent = p_parent;
m__root = this;
m_some_int = m__io->read_u4le();
m_some_string = m__io->read_str_byte_limit((some_int() + 4), "UTF-8");
m_another_int = m__io->read_u4le();
}
Run Code Online (Sandbox Code Playgroud)
或者在Java中:
private void _parse() throws IOException {
this.someInt = this._io.readU4le();
this.someString = this._io.readStrByteLimit((someInt() + 4), "UTF-8");
this.anotherInt = this._io.readU4le();
}
Run Code Online (Sandbox Code Playgroud)
将它添加到您的项目后,它提供了一个非常直观的API(Java中的一个示例,但它们支持更多语言):
// given file.dat contains 01 00 00 00|41 42 43 44|07 01 00 00
MyStruct s = MyStruct.fromFile("path/to/file.dat");
s.someString() // => "ABCD"
s.anotherInt() // => 263 = 0x107
Run Code Online (Sandbox Code Playgroud)
它支持不同的字节顺序,条件结构,子结构等,还有更多.可以解析非常复杂的数据结构,例如PNG图像文件格式或PE可执行文件.
您可以尝试使用Boost.Spirit(v2),它最近获得了二进制解析工具,字节序感知本机和混合 解析器
// This is not a complete and useful example, but just illustration that parsing
// of raw binary to real data components is possible
typedef boost::uint8_t byte_t;
byte_t raw[16] = { 0 };
char const* hex = "01010000005839B4C876BEF33F83C0CA";
my_custom_hex_to_bytes(hex, raw, 16);
// parse raw binary stream bytes to 4 separate words
boost::uint32_t word(0);
byte_t* beg = raw;
boost::spirit::qi::parse(beg, beg + 16, boost::spirit::qi::dword, word))
Run Code Online (Sandbox Code Playgroud)
更新:我发现了类似的问题,Joel de Guzman在答案中证实了二进制解析器的可用性:可以使用Boost Spirit来解析字节流数据吗?