Автоматически генерировать имена файлов без коллизий - PullRequest
2 голосов
/ 31 марта 2009

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

Более того, я не хочу генерировать имя и искать в базе данных, чтобы увидеть, существует ли файл уже. Я хочу убедиться, что мое приложение никогда не создавало ранее созданное имя файла на 100% или 99%.

Есть идеи, как написать такое приложение?

Ответы [ 5 ]

10 голосов
/ 31 марта 2009

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

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

  2. Вы отделяете метаданные (имя файла - это просто метаданные) от BLOB-объекта. Таким образом, у вас будет система хранения, которая индексируется хэшем содержимого файла, и затем вы связываете метаданные файла с этим хэш-кодом поиска.

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

3 голосов
/ 31 марта 2009

Лучшее решение уже упоминалось. Я просто хочу добавить несколько мыслей.

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

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

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

Кроме того, Coommon хранит файлы в структуре каталогов, где местоположение файла зависит от его имени. Файл abcdef1234.xyz может храниться как /ab/cd/ef/1234.xyz. Это позволяет избежать каталогов с огромным количеством файлов. Я не совсем понимаю, почему это делается - могут быть ограничения файловой системы, проблемы с производительностью - но это довольно часто. Я не знаю, распространены ли подобные вещи, если файлы хранятся непосредственно в базе данных.

3 голосов
/ 31 марта 2009

GUID являются односторонними. Вы гарантированно не получите повторов (если у вас есть подходящий генератор случайных чисел).

2 голосов
/ 31 марта 2009

Вы также можете добавить со временем, начиная с эпохи.

1 голос
/ 31 марта 2009

Лучший способ - просто использовать счетчик. Первый файл - 1, следующий - 2, другой - 3 и т. Д. ...

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

file = last_file + random(1 through 10)
...