Действительно уникальное случайное число генерируется с помощью php?
Я создал скрипт php для размещения большого количества изображений, загружаемых пользователем, каков наилучший способ создания случайных чисел для имен файлов изображений, чтобы в будущем не было конфликта имен файлов? Будь как Imageshack. Благодарю.
10 ответов
Сохраняйте постоянный список всех предыдущих сгенерированных вами чисел (в таблице базы данных или в файле) и проверяйте, чтобы вновь сгенерированный номер не входил в список. Если вы обнаружите, что это слишком дорого, генерируйте случайные числа на достаточном количестве битов, чтобы гарантировать очень низкую вероятность столкновения.
Вы также можете использовать инкрементный подход к назначению этих чисел, например, объединение timestamp_part на основе текущего времени и random_part, просто чтобы убедиться, что вы не получите коллизии, если несколько пользователей загружают файлы одновременно.
Самым простым способом будет новый GUID для каждого файла.
Вот как я реализовал ваше решение
В этом примере предполагается, что я хочу
- Получить список, содержащий 50 чисел, уникальных и случайных, и
- Этот список # поступить из диапазона номеров от 0 до 1000
Код:
//developed by www.fatphuc.com
$array = array(); //define the array
//set random # range
$minNum = 0;
$maxNum = 1000;
// i just created this function, since we’ll be generating
// # in various sections, and i just want to make sure that
// if we need to change how we generate random #, we don’t
// have to make multiple changes to the codes everywhere.
// (basically, to prevent mistakes)
function GenerateRandomNumber($minNum, $maxNum){
return round(rand($minNum, $maxNum));
}
//generate 49 more random #s to give a total of 50 random #s
for($i = 1; $i <= 49; $i++){
$num1 = GenerateRandomNumber($minNum, $maxNum);
while(in_array($num1, $array)){
$num1 = GenerateRandomNumber($minNum, $maxNum);
}
$array[$i] = $num1;
}
asort($array); //just want to sort the array
//this simply prints the list of #s in list style
echo '<ol>';
foreach ($array as $var){
echo '<li>';
echo $var;
echo '</li>';
}
echo '</ol>';
В вашем постулате есть несколько недостатков, согласно которым случайные значения будут уникальными - независимо от того, насколько хорош генератор случайных чисел. Кроме того, чем лучше генератор случайных чисел, тем больше времени требуется для вычисления результатов.
Не лучше ли использовать хеш файла данных - таким образом вы получаете дополнительное преимущество обнаружения дублированных представлений.
Если известно, что обнаружение дубликатов не является проблемой, то я все равно рекомендую этот подход, но изменяю выходные данные на основе обнаруженных коллизий (но используя гораздо более дешевый метод вычисления, чем тот, который был предложен Lo'oris), например
$candidate_name=generate_hash_of_file($input_file);
$offset=0;
while ((file_exists($candidate_name . strrev($offset) && ($offset<50)) {
$offset++;
}
if ($offset<50) {
rename($input_file, $candidate_name . strrev($offset));
} else {
print "Congratulations - you've got the biggest storage network in the world by far!";
}
это даст вам возможность хранить около 25*2^63 файлов с использованием хэша sha1.
Что касается того, как генерировать хеш, чтение всего файла в PHP может быть медленным (особенно если вы пытаетесь прочитать все это в одну строку, чтобы хэшировать его). Большинство систем Linux/Posix/Unix поставляются с такими инструментами, как 'md5sum', которые очень эффективно генерируют хэш из потока.
C.
Вы можете использовать microtime(), как предложено выше, а затем добавить хеш исходного имени файла, чтобы дополнительно избежать коллизий в (редком) случае точных современных загрузок.
- подделать имя файла
- попробуйте открыть этот файл
- если он существует, переходите к 1
- создать файл
Гарантированная уникальность не может быть случайной. Случайное не может быть гарантировано уникальным. Если вы хотите уникальный (без случайного), тогда просто используйте целые числа: 0, 1, 2, ... 1235, 1236, 1237, ... Определенно уникальный, но не случайный.
Если это не устраивает, то вы можете быть совершенно уникальным с появлением случайных. Вы используете шифрование целых чисел, чтобы они выглядели случайными. Использование DES даст вам 32-битные числа, в то время как использование AES даст вам 64-битные числа. Используйте либо для шифрования 0, 1, 2,... в порядке с тем же ключом. Все, что вам нужно сохранить, это ключ и следующий номер для шифрования. Поскольку шифрование является обратимым, то зашифрованные номера гарантированно уникальны.
Если 64-битные или 32-битные числа слишком велики (32 бита - это 8 шестнадцатеричных цифр), посмотрите на формат, сохраняющий шифрование, который даст вам меньший размерный диапазон при некоторых затратах времени.
Моим решением обычно является хеш (MD5/SHA1/...) содержимого изображения. Это дает дополнительное преимущество: если люди загружают одно и то же изображение дважды, у вас остается только одно изображение на жестком диске, что экономит некоторое пространство (конечно, вы должны убедиться, что изображение не удалено, если один пользователь удаляет его, а другой пользователь имеет то же изображение в использовании).