Двоичная генерация патчей в C # - PullRequest
15 голосов
/ 08 августа 2008

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

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

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

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

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

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

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

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

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

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

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


Редактировать # 1 : Вот более подробное описание вышеприведенного алгоритма.

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

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

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


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

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

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


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

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

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

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

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

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

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

Редактировать # 2 : Я обязательно поищу реализацию xdelta на python.

Ответы [ 6 ]

4 голосов
/ 30 декабря 2010

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

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

4 голосов
/ 08 августа 2008

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

3 голосов
/ 07 сентября 2008

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

1 голос
/ 08 августа 2008

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

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

1 голос
/ 08 августа 2008

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

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

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

0 голосов
/ 05 мая 2009

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

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

...