Генерация бинарных патчей на C#

Есть ли у кого-нибудь или знает о реализации алгоритма генерации бинарных патчей на C#?

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

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

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

Любые советы или указатели по реализации были бы хороши.

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

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

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

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

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

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


Изменить № 1 : Вот более подробное описание вышеуказанного алгоритма.

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

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

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


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

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

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


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

А может я просто тупой ... :)

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

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

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

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

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

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

Ответов (6)

Решение

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

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

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

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

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

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

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

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

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

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

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