所以,我收到了这些数据。从网络套接字,或从文件中。我正在拼凑将解释数据的代码。读取一些字节,检查一些标志,一些字节表示后面有多少数据。读入那么多数据,冲洗,重复。
这个任务让我想起解析源代码。我对lex / yacc和antlr很满意,但他们不能胜任这项任务。你不能将比特和原始字节指定为标记(好吧,也许你可以,但我不知道如何),你不能把它们哄成“读取两个字节,使它们成为无符号的16位整数,称之为 n ,然后读取 n 字节。“。
然后,当以系统方式定义协议/数据格式的规范(并非所有规范都是)时,应该有一种系统的方式来读取根据协议格式化的数据。对?
必须有一个工具才能做到这一点。
答案 0 :(得分: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
使用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();
}
或在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();
}
将它添加到您的项目后,它提供了一个非常直观的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
它支持不同的字节序,条件结构,子结构等等。可以解析非常复杂的数据结构,例如PNG image file format或PE executable。
答案 1 :(得分:8)
您可以尝试使用Boost.Spirit(v2),该binary parsing tools(v2)最近得到native,有字节感知mixed和parsers Can Boost Spirit be used to parse byte stream data?
// 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))
更新:我发现了类似的问题,Joel de Guzman在答案中证实了二进制解析器的可用性:{{3}}
答案 2 :(得分:2)
用Python编写的Construct解析器在这个领域做了一些有趣的工作。
该项目有许多作者和停滞期,但截至2017年,它似乎再次变得更加活跃。
答案 3 :(得分:1)
阅读ASN.1。如果您可以用其术语描述二进制数据,则可以使用各种可用的工具包。不适合胆小的人。
答案 4 :(得分:1)
答案 5 :(得分:0)
当然,没有什么可以阻止你编写一个递归的正确解析器,比如二进制数据,就像你手工工具文本解析器一样。如果您需要阅读的格式不太复杂,这是一种合理的方式。
当然,如果格式为非常,您可以查看Reading binary file defined by a struct和类似的问题。
我不知道任何用于非文本输入的解析器生成器,尽管这些也是可能的。
如果您不熟悉手动编码解析器,则规范的SO问题为Learning to write a compiler。 Crenshaw tutorial(和in PDF)是快速阅读。
答案 6 :(得分:0)
另请参阅google协议缓冲区。
答案 7 :(得分:0)
有一个名为binpac的工具就是这样做的。
http://www.icsi.berkeley.edu/pubs/networking/binpacIMC06.pdf