Генерация двоичных патчей в С#

Кто-нибудь знает или знает о реализации алгоритма генерации двоичных патчей в С#?

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

Реализация должна быть относительно быстрой и работать с огромными файлами. Он должен демонстрировать время работы O (n) или O (logn).

Мои собственные алгоритмы имеют тенденцию либо быть паршивыми (быстрыми, но производят огромные исправления), либо медленными (производят небольшие патчи, но имеют O (n ^ 2) время выполнения).

Любые советы или указатели для реализации будут приятными.

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

Самый наивный алгоритм, который я сделал, который работает только для файлов, которые могут храниться в памяти, выглядит следующим образом:

  • Возьмите первые четыре байта из старого файла, назовите это клавишей
  • Добавьте эти байты в словарь, где key → position, где позиция - это позиция, в которой я захватил эти 4 байта, 0, чтобы начать с
  • Пропустите первый из этих четырех байтов, возьмите еще 4 (3 перекрытия, 1 один) и добавьте в словарь таким же образом
  • Повторите шаги 1-3 для всех 4-байтовых блоков в старом файле
  • С самого начала нового файла возьмите 4 байта и попытайтесь найти его в словаре
  • Если найдено, найдите самое длинное совпадение, если их несколько, сравнив байты из двух файлов
  • Кодировать ссылку на это место в старом файле и пропустить соответствующий блок в новом файле
  • Если не найден, закодируйте 1 байт из нового файла и пропустите его
  • Повторите шаги 5-8 для остальной части нового файла.

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

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

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


Изменить # 1. Ниже приведено более подробное описание алгоритма.

Сначала объедините два файла, чтобы у вас был один большой файл. Помните точку пересечения между двумя файлами.

Во-вторых, сделайте это, захватите 4 байта и добавьте их позицию на шаг словаря для всего, что находится во всем файле.

В-третьих, начиная с того места, где начинается новый файл, выполните цикл с попыткой найти существующую комбинацию из 4 байтов и найдите самое длинное совпадение. Удостоверьтесь, что мы рассматриваем только позиции из старого файла или ранее в новом файле, чем в настоящее время. Это гарантирует, что мы можем повторно использовать материал как в старом, так и в новом файле во время применения патча.


Изменить # 2: Исходный код для вышеуказанного алгоритма

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

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


@lomaxx, я попытался найти хорошую документацию для алгоритма, используемого в subversion, называемого xdelta, но если вы уже не знаете, как работает алгоритм, документы, которые я нашел, не могут сказать мне, что мне нужно знать.

Или, может быть, я просто плотный...:)

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

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

Мои потребности не оптимальны, поэтому я ищу более практичное решение.

Спасибо за ответ, хотя добавили закладку в его утилиты, если они мне понадобятся.

Изменить # 1: Заметьте, я посмотрю на его код, чтобы узнать, могу ли я найти некоторые идеи, и я также отправлю ему электронное письмо позже с вопросами, но я прочитал эту книгу, которую он ссылается, и хотя решение хорошо подходит для поиска оптимальных решений, это нецелесообразно в использовании из-за требований времени.

Изменить # 2. Я определенно выслежу реализацию python xdelta.

Ответы

Ответ 1

Жаль, что больше не помогала. Я бы определенно продолжал смотреть на xdelta, потому что я использовал его несколько раз, чтобы произвести качественные различия с файлами 600MB + ISO, которые мы создали для распространения наших продуктов, и он работает очень хорошо.

Ответ 2

bsdiff был разработан для создания очень маленьких патчей для двоичных файлов. Как указано на его странице, для этого требуется max(17*n,9*n+m)+O(1) байт памяти и работает в O((n+m) log n) времени (где n - размер старого файла, а m - размер нового файла).

Исходная реализация находится на C, но порт С# описывается здесь и доступен .

Ответ 3

Вы видели VCDiff? Это часть библиотеки Misc, которая выглядит довольно активной (последний выпуск r259, 23 апреля 2008 г.). Я не использовал его, но думал, что стоит упомянуть.

Ответ 4

Возможно, стоит проверить, что делают некоторые из других парней в этом пространстве, а не обязательно на арене С#.

Это библиотека, написанная в С#

SVN также имеет бинарный алгоритм diff, и я знаю, что реализация в python, хотя я не смог найти его с помощью быстрого поиска. Они могут дать вам несколько идей о том, где можно улучшить собственный алгоритм.

Ответ 5

Если это касается установки или распространения, рассмотрели ли вы использование SDK установщика Windows? Он имеет возможность исправлять двоичные файлы.

http://msdn.microsoft.com/en-us/library/aa370578(VS.85).aspx

Ответ 6

Это приблизительная рекомендация, но для алгоритма rsync можно использовать следующие алгоритмы, которые можно использовать для создания ваших двоичных патчей.

http://rsync.samba.org/tech_report/tech_report.html