Назовите мне двоичный парсер. Парсер для двоичных данных [закрыт]

Итак, я получаю эти данные. Из сетевого сокета или из файла. Я собираю код, который будет интерпретировать данные. Прочитайте некоторые байты, проверьте некоторые флаги, а некоторые байты указывают, сколько данных следует за ними. Прочтите столько данных, промойте, повторите.

Эта задача очень напоминает мне парсинг исходного кода. Мне удобно с lex/yacc и antlr, но они не справляются с этой задачей. Вы не можете указать биты и необработанные байты как токены (ну, может быть, вы могли бы, но я не знаю, как), и вы не можете уговорить их «прочитать два байта, превратить их в беззнаковое 16-битное целое, назовите это n, а затем прочитать n байт.".

Опять же, когда спецификация протокола/формата данных определяется систематическим образом (не все из них), должен быть систематический способ чтения данных, отформатированных в соответствии с протоколом. Правильно?

Должен быть инструмент, который это делает.


person doppelfish    schedule 06.02.2010    source источник
comment
голосование за повторное открытие, потому что это не столько поиск рекомендаций, сколько выяснение того, существует ли определенный вид технологии. я нашел эту страницу очень актуальной и полезной, и я ненавижу думать, что она скрыта от тех, у кого нет привилегии закрытия / повторного открытия   -  person pestophagous    schedule 26.02.2021


Ответы (8)


Вы можете попробовать использовать 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))

ОБНОВЛЕНИЕ: я нашел аналогичный вопрос, где Джоэл де Гусман подтверждает в своем ответе наличие бинарных парсеров: Можно ли использовать Boost Spirit для анализа данных потока байтов?

person mloskot    schedule 06.02.2010
comment
Это выглядит многообещающе. Спасибо! - person doppelfish; 07.02.2010

Недавно появилась инициатива 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 или исполняемый файл PE может быть проанализирован.

person dpm_min    schedule 02.10.2016

Парсер Construct, написанный на Python, проделал интересную работу в этой области.

У проекта было несколько авторов и периоды застоя, но с 2017 года он снова стал более активным.

person Craig McQueen    schedule 19.10.2010
comment
Похоже, кто-то недавно занимался техническим обслуживанием. У них также есть новые документы. - person dowski; 27.11.2012

Почитайте ASN.1. Если вы можете описать двоичные данные в их терминах, вы можете использовать различные доступные наборы. Не для слабонервных.

person bmargulies    schedule 06.02.2010

https://github.com/lonelybug/ddprotocol/wiki/Getting-Start

надеюсь, что это полезно для вас.

person noname    schedule 02.10.2012
comment
Одинокая ссылка не работает, пожалуйста, дайте краткое описание. - person Austin Henley; 03.10.2012
comment
Извини за это. пожалуйста, забыл эту ссылку, я собираюсь как-нибудь реорганизовать этот инструмент. - person noname; 01.11.2012

Конечно, ничто не мешает вам написать достойный рекурсивный синтаксический анализатор, скажем, для двоичных данных, точно так же, как вы вручную настроили бы текстовый синтаксический анализатор. Если формат, который вам нужно прочитать, не слишком сложен, это разумный способ продолжить.

Конечно, если вы форматируете очень просто, вы можете взглянуть на Чтение бинарного файла, определенного структурой, и аналогичный вопрос.

Я не знаю никаких генераторов парсеров для нетекстового ввода, хотя они тоже возможны.


В случае, если вы не знакомы с парсерами кодирования вручную, канонический вопрос SO: Учимся писать компилятор. руководство Crenshawв формате PDF) читается быстро.

person dmckee --- ex-moderator kitten    schedule 06.02.2010
comment
Ну, я по сути пишу синтаксический анализатор таким образом. Вручную, то есть. Но разве я первый человек на земле, который это сделал? - person doppelfish; 07.02.2010

См. также буферы протокола Google.

person fche    schedule 24.03.2011
comment
Это действительно комментарий, а не ответ на вопрос. Пожалуйста, используйте комментарий, чтобы оставить отзыв об авторе. - person Thor; 16.08.2012

Существует инструмент под названием binpac, который делает именно это.

http://www.icsi.berkeley.edu/pubs/networking/binpacIMC06.pdf

person Albin Stigo    schedule 30.05.2015