Parsing 给我命名一个二进制解析器。二进制数据的解析器

Parsing 给我命名一个二进制解析器。二进制数据的解析器,parsing,binary,protocols,Parsing,Binary,Protocols,所以,我得到了这些数据。从网络套接字或从文件中取出。我正在拼凑解释数据的代码。读取一些字节,检查一些标志,一些字节指示后面有多少数据。读入那么多数据,冲洗,重复 这个任务让我想起了很多解析源代码的事情。我对lex/yacc和antlr很满意,但他们不能胜任这项任务。您不能将位和原始字节指定为标记(嗯,也许可以,但我不知道如何指定),也不能将它们诱使为“读取两个字节,将它们变成一个无符号16位整数,称之为n,然后读取n个字节” 然后,当协议/数据格式的规范以系统的方式定义时(并非所有规范都是系统的

所以,我得到了这些数据。从网络套接字或从文件中取出。我正在拼凑解释数据的代码。读取一些字节,检查一些标志,一些字节指示后面有多少数据。读入那么多数据,冲洗,重复

这个任务让我想起了很多解析源代码的事情。我对lex/yacc和antlr很满意,但他们不能胜任这项任务。您不能将位和原始字节指定为标记(嗯,也许可以,但我不知道如何指定),也不能将它们诱使为“读取两个字节,将它们变成一个无符号16位整数,称之为n,然后读取n个字节”

然后,当协议/数据格式的规范以系统的方式定义时(并非所有规范都是系统的),应该有一种系统的方式来读取根据协议格式化的数据。对吧?


一定有一个工具可以做到这一点。

请阅读ASN.1。如果可以用术语描述二进制数据,那么可以使用各种可用的工具包。不适合胆小的人。

毫无疑问,没有什么能阻止你编写一个递归的、像样的解析器,比如说,对于二进制数据,就像你手工编写文本解析器一样。如果您需要阅读的格式不是太复杂,那么这是一种合理的方法

当然,如果你的格式很简单,你可以看看和类似的问题

我不知道有任何用于非文本输入的解析器生成器,尽管它们也是可能的


如果您不熟悉手工编写解析器,那么规范的SO问题就是。(and)是一种快速阅读方式。

您可以尝试使用(v2),它最近获得了endianness感知和

更新:我发现了类似的问题,Joel de Guzman在他的回答中确认了二进制解析器的可用性:

用Python编写的解析器在这个领域做了一些有趣的工作


该项目有很多作者,也有过停滞期,但截至2017年,它似乎又变得更加活跃了。

另见谷歌协议缓冲区。


希望这对您有所帮助。

有一个名为binpac的工具,它可以做到这一点

最近出现了一项倡议,旨在解决这项任务:从规范生成二进制解析器。您可以提供一种方案,用于以基于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中的一个示例,但它们支持更多语言):


它支持不同的端点、条件结构、子结构等,等等。相当复杂的数据结构,例如or,可以被解析。

好吧,我基本上就是用这种方式编写解析器的。那是手工的。但我是地球上第一个这样做的人吗?这看起来很有希望。非常感谢。这实际上是一个评论,而不是对问题的回答。请使用“添加评论”为作者留下反馈。单独的链接不好,请提供摘要。对此表示抱歉。请忘记这个链接,我将以某种方式重构这个工具。看起来最近有人开始维护了。他们也投票决定重新开放,因为这不是为了寻求推荐,而是为了找出某种技术是否存在。我发现这个页面非常相关和有用,我讨厌认为它对那些没有关闭/重新打开特权的人是隐藏的
private void _parse() throws IOException {
    this.someInt = this._io.readU4le();
    this.someString = this._io.readStrByteLimit((someInt() + 4), "UTF-8");
    this.anotherInt = this._io.readU4le();
}
// 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