Поиск двоичных данных в Ruby - PullRequest
       0

Поиск двоичных данных в Ruby

1 голос
/ 06 августа 2010

Используя только чистый рубин (или оправданно распространенные гемы), существует ли эффективный способ поиска в большом двоичном документе по определенной строке байтов?


Более глубокий контекст:Контейнерный формат mpeg4 представляет собой 4-байтовую индексированную сериализованную структуру данных, без необходимости полного анализа структуры (могу предположить, что она действительна). Я хочу извлечь определенные теги.

Для тех из вас, кто еще ненатолкнитесь на эту сериализацию 'dmap', прежде чем она сработает примерно так:

<4-byte length<4-byte tag><4-byte length><4-byte type definition><8 bytes of something I can't remember><data>

например, это определяет тег 'tvsh' (или TV Show) как 'Futurama'

00 00 00 20  ... 
74 76 73 68  tvsh
00 00 00 18  ....
64 61 74 61  data
00 00 00 01  ....
00 00 00 00  ....
46 75 74 75  Futu
72 61 6D 61  rama

Точная структура не очень важна, я хотел бы написать метод, который может вытащить название шоу, когда я дам ему 'tvsh' или что это сезон 2, если я дам ему 'tvsn'.

Мой первый план - использовать регулярные выражения, но у меня возникает (неоправданное) ощущение, что это будет медленно.

Дайте мне знать ваши мысли!Заранее спасибо

Ответы [ 3 ]

1 голос
/ 07 августа 2010

В Ruby вы можете использовать флаг /n при создании регулярного выражения, чтобы сообщить Ruby, что вы вводите 8-битные данные.

Вы можете использовать /(.{4})tvsh(.{4})data(.{8})([\x20-\x7F]+)/n для соответствия 4 байта, tvsh4 байта, data, 8 байтов и любое количество символов ASCII.Я не вижу причин, по которым это регулярное выражение будет выполняться значительно медленнее, чем кодирование подобного поиска вручную.Если вам не нужны 4-байтовые и 8-байтовые блоки, /tvsh.{4}data.{8}([\x20-\x7F])/n должен быть почти таким же быстрым, как буквальный текстовый поиск для tvsh.

1 голос
/ 06 августа 2010

Если я правильно понимаю ваше описание, весь файл состоит из ряда таких «блоков» фиксированной структуры?

В этом случае я предлагаю сканировать по одному и пропускать те, которые вам не интересны. Итак, каждый ваш шаг должен делать следующее:

  1. Читать 8 байтов (используя IO#readbytes или аналогичный метод)
  2. Из заголовка чтения извлеките size (первые 4 байта) и tag (вторые 4)
    1. Если вам нужен тег, пропустите следующие 16 байт и прочитайте size-24 байт.
    2. Если тег не представляет интереса, пропустите следующие size-16 байты.
  3. Повторите.

Для пропуска байтов вы можете использовать IO#seek.

0 голосов
/ 07 августа 2010

Теоретически вы можете использовать регулярные выражения для любых произвольных данных, включая двоичные строки. НТН.

...