как найти смещение одного двоичного файла в другом?

Я зафиксировал это теперь.

Во-первых, я не устанавливал, сжимают с Рабочей средой GNOME по умолчанию. Я неправильный помнивший. То, что я сделал, было установить основную систему и затем установить пакет рабочей среды GNOME, стремясь к lighter/closer-to-upstream набору пакетов.

Теперь, полностью нес научной точки зрения, я сделал две вещи сразу для фиксации этого, таким образом, я не знаю наверняка, который сделал это. Я решил установить настольную задачу GNOME Debian (tasksel install gnome-desktop --new-install). Я думал, что, возможно, так или иначе, рабочая среда GNOME не вытягивала в правильных пакетах для добавления этой функциональности. Ретроспективно, я думаю, что это маловероятно.

Затем, я перезапустил машину. Я был уверен, что перезапустил машину после установки рабочей среды GNOME, но теперь я думаю, что не имел. Таким образом, по-видимому, некоторые сервисы не работали правильно, или что-то как этот.

После перезапуска вещи работали точно, как я хотел - устройства хранения USB монтировались автоматически в / медиа/, который является большим.

6
31.05.2012, 13:05
4 ответа

Я не мог придумать существующий инструмент.

grep -F --binary --byte-offset --only-matching кажется, достаточно близок - но Вы не можете выйти из новых строк с -F. И cmp только позволяет пропускать символы. diff также, кажется, не помогает.

Но это - некоторые лайнер на языке программирования с достойной библиотекой. Например, как программа C++ с помощью Повышения:

#include <boost/algorithm/string/find.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <cassert>
#include <iostream>
using namespace boost;
using namespace boost::algorithm;
using namespace boost::iostreams;
using namespace std;

int main(int argc, char **argv)
{
  if (argc != 3) {
    cerr << "Call: " << argv[0] << " PATTERN_FILE SRC_FILE\n";
    return 3;
  }
  mapped_file_source pattern(argv[1]);
  mapped_file_source src(argv[2]);
  iterator_range<const char*> p_range(pattern.data(),
      pattern.data() + pattern.size());
  iterator_range<const char*> s_range(src.data(), src.data() + src.size());
  iterator_range<const char*> result = find_first(s_range, p_range);
  if (result) {
    size_t pos = result.begin()-s_range.begin();
    cout << pos << '\n';
    return 0;
  }
  return 1;
}

Можно скомпилировать его как это (когда источник программы сохраняется как find.cc):

$ make CXXFLAGS="-Wall -g" LDLIBS="-lboost_iostreams" searchb

Протестировать его:

$ dd if=WTF_-_EPISODE_277_RACHAEL_HARRIS.mp3 of=t skip=232323 bs=1 count=4K
$ ls -l t
-rw-r--r-- 1 juser users 4096 2012-05-31 15:24 t
$ ./searchb t WTF_-_EPISODE_277_RACHAEL_HARRIS.mp3
232323

Вывод является положением соответствия в исходном файле.

Если файл не содержится, статус выхода 1.

Обновление: Тем временем я реализовал этот простой инструмент на нескольких языках (C/C ++/Python/Rust/Go) и включал те реализации в мой служебный репозиторий. Искать searchb*. Реализация Python является самой короткой и не требует никаких внешних зависимостей.

4
27.01.2020, 20:29
  • 1
    большое спасибо. это загружает целый файл шаблона в память? –  Cyryl Płotnicki 31.05.2012, 17:49
  • 2
    также это делает это: оконечный названный после броска экземпляра 'повышения:: exception_detail:: clone_impl <повышение:: exception_detail:: error_info_injector <станд.:: исключение>>', что (): станд.:: Прерванное исключение (выведенное ядро) –  Cyryl Płotnicki 31.05.2012, 18:28
  • 3
    @CyrylPlotnicki-Chudyk, не действительно, это (ядро) карты распределения памяти файл в виртуальную память. Таким образом это зависит от системы виртуальной памяти ядра (и Ваши имеющиеся ресурсы), сколько из шаблона загружается в память во время осуществления программы. –  maxschlepzig 31.05.2012, 18:36
  • 4
    @CyrylPlotnicki-Chudyk, ошибка означает что, отображая файл в отказавшую память. Возможно, предел виртуальной памяти достигнут, или файловая система не поддерживает размещение в ОЗУ. Насколько большой Ваши файлы точно? Какое распределение и какую архитектуру Вы используете (64/32 бита)? –  maxschlepzig 31.05.2012, 18:54
  • 5
    Эй, спасибо за Ваш ответ! На самом деле это - Fedora 16, 32 бита, с ~500kb шаблоном и файлы –  Cyryl Płotnicki 01.06.2012, 07:51

Вот сценарий Python, который выполняет поиск подстроки на внешнем файле. Сценарий был первоначально записан Kamran Khan и размещен в его блоге. Я очень немного адаптировал его для взятия строки поиска из файла и поиска в стандартном входе.

#!/usr/bin/env python
import locale
import os
import sys
import urllib2

def boyermoore_horspool(fd, needle):
    nlen = len(needle)
    nlast = nlen - 1

    skip = []
    for k in range(256):
        skip.append(nlen)
    for k in range(nlast):
        skip[ord(needle[k])] = nlast - k
    skip = tuple(skip)

    pos = 0
    consumed = 0
    haystack = bytes()
    while True:
        more = nlen - (consumed - pos)
        morebytes = fd.read(more)
        haystack = haystack[more:] + morebytes

        if len(morebytes) < more:
            return -1
        consumed = consumed + more

        i = nlast
        while i >= 0 and haystack[i] == needle[i]:
            i = i - 1
        if i == -1:
            return pos

        pos = pos + skip[ord(haystack[nlast])]

    return -1

if __name__ == "__main__":
    if len(sys.argv) < 2:
        sys.stderr.write("""Usage: horspool.py NEEDLE_FILE [URL]
Search for the contents of NEEDLE_FILE inside the content at URL.
If URL is omitted, search standard input.
If the content is found, print the offset of the first occurrence and return 0.
Otherwise, return 1.""")
        sys.exit(2)
    needle_file = open(sys.argv[1])
    needle = needle_file.read()
    needle_file.close
    fd = urllib2.urlopen(sys.argv[2]) if len(sys.argv) > 2 else sys.stdin
    offset = boyermoore_horspool(fd, needle)
    if offset >= 0: print offset
    else: sys.exit(1)
    fd.close()
0
27.01.2020, 20:29

Если у вас есть память, просто прочитайте большой файл кусками размером с меньший. После того, как каждый фрагмент прочитан, объедините последние два фрагмента, прочитанные вместе, а затем выполните строковый поиск результата. В Python 3.8+ код выглядит так:

def find_at_offset(large_fp, small_fp):
    small = small_fp.read()
    blocks = [b"", b""]
    base = 0
    while blk := large_fp.read(len(small)):
        base += len(blocks[0])
        del blocks[0]
        blocks.append(blk)
        offset = b"".join(blocks).find(small)
        if offset != -1:
            return base + offset
    return -1

Концепция очень проста, хорошо переводится на старый добрый C и не требует каких-либо специальных функций, таких как отображение памяти. Предостережение заключается в том, что для этого требуется минимальный доступный объем памяти, равный 3 -5-кратному размеру небольшого файла, в зависимости от того, как вы его реализуете. Преимущество в том, что это очень быстро, потому что он использует простой строковый поиск, который очень оптимизирован.

0
26.11.2020, 22:39

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

BLAT — самое быстрое решение, которое я знаю:https://en.wikipedia.org/wiki/BLAT_(биоинформатика)

Он строит индекс и после построения индекса работает невероятно быстро.

1
27.11.2020, 11:19

Теги

Похожие вопросы