Алгоритм определения идентичности файла (оптимизация)

далее к этому вопросу:алгоритм определения идентификатора файла

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

Я пошел вперед и реализован алгоритм, который дает мне "уникальный" хэш для каждого файла.

мой алгоритм работает следующим образом:

  • для файлов меньше определенного порога Я использую полное содержимое файлов для хэша идентификаторов.

  • для файлов больше порога я беру случайные N выборок размера X.

  • Я включаю размер файла в хэшированные данные. (это означает, что все файлы с разными размерами приводят к другому хэшу)

вопросы:

  • какие значения я должен выбрать для N и X (сколько случайных выборок я должен принять какого размера?) Я пошел с 4 образцы 8K каждый и не в состоянии поставить алгоритм в тупик. Я обнаружил, что увеличение количества выборок быстро уменьшает скорость алгоритма (поиск причины довольно дорог)

  • математика один:как разные мои файлы должны быть для этого алгоритма, чтобы взорвать. (2 разных файла с одинаковой длиной в конечном итоге имеют один и тот же хэш)

  • оптимизация: есть ли какие-либо способы оптимизировать мою конкретную реализацию для улучшите пропускную способность (кажется, я могу делать около 100 файлов в секунду в моей системе).

  • выглядит ли эта реализация вменяемой? Видите ли вы реальные примеры, где это не удастся. (Мое внимание сосредоточено на медиафайлах)

соответствующая информация:

алгоритм, который я реализовал

Спасибо за вашу помощь!

3 ответов


  • всегда включать 1-й и последний блок файла в хэш.

это потому, что они, скорее всего, будет отличаться от файла к файлу. Если вы считаете BMP, он может иметь довольно стандартный заголовок (например, 800x600 image, 24bit, null rest), поэтому вы можете немного перескочить заголовок, чтобы добраться до дифференцирующих данных. Проблема в том, что заголовки сильно различаются по размеру.

последний блок предназначен для fileformats, которые добавляют данные к оригинальный.

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

даже тогда, если вам не повезет, вы неправильно идентифицируете некоторые файлы как одинаковые (например, файл базы данных SQL Server, и это 1:1 резервная копия после нескольких вставок; за исключением того, что SS пишет метку времени..)


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

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

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

некоторые мысли о работе. Для небольших файлов вероятность равной длины файла довольно высока - существует не так много разных небольших длин файлов. Но это не дорого для хеширования файлов.

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

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

обновление

для фильмов я бы счел длину файла практически уникальной, но файлы, перекодированные, чтобы поместиться на данном носителе, вероятно, делают эту идею пустой - (Ы)фильмы VCD будут находиться в небольшом диапазоне длин файлов о емкости CD-ROM.

но для файлов фильмов в вообще, я бы просто хэшировал один блок (возможно, 512 байт) из середины файла. Два разных фильма с одним и тем же изображением и звуком в одной и той же позиции? Практически невозможно, кроме того, вы манипулируете файлами, чтобы провалить этот тест. Но вы можете легко генерировать файлы, чтобы провалить все детерминированные стратегии выборки - так что это не должно иметь большого значения.


  1. Не ищите назад и не открывайте файл с помощью FILE_FLAG_SEQUENTIAL_SCAN (в Windows).
    (Выберите X случайных чисел, а затем отсортировать их).
  2. искать далеко, есть usuauely некоторые данные в кэш для чтения впереди.
  3. если у вас есть большие файлы форматировать раздел, чтобы иметь большой размер сектора.
  4. вы возвращаете идентификатор Guid для идентификатора, должны хэшировать алгоритмы более 128 бит.