Уникальные названия файлов

kennedy

Новичок
Уникальные названия файлов

Нужно создавать уникальные названия файлов
как пример
youtube watch?v=0maYqj6jpv0
intv /v/2XdhJpqTON

по какому алгоритму создаются эти названия?

нужно что то не слишком длинное но уникальное.
 

lart

Guest
Берешь microtime() и шифруешь его, каким то шифром, и получишь практически уникальное имя.

P.S. практически уникальное, потому что могут возникать коллизии и совпадения, но это очень редкий случай
 

kennedy

Новичок
"и шифруешь его, каким то шифром"
вот тут по подробнее

а так что б привязать к названию файла а не времени создания?

какой то минимд5:)
 

dimagolov

Новичок
есть base62 кодирование чисел, которым длинные числа превращаются в короткие строки. если время с точностью до миллисекунд, то уникальность практически абсолютная. в любом случае коллизия очень просто разрешается.

-~{}~ 30.08.10 16:47:

п.с. можно и значение md5 кодировать в base62, перевод из 16 в 62-разрядную систему счисления даст сокращение до 9 символов вместо 32-х
 

A1x

Новичок
я обычно беру массив из букв и цифр в цикле N раз делаю над ним shuffle и выбираю случайный элемент. Уникальность меня вполне устраивала
 

kennedy

Новичок
нужно привязать к названию файла а не времени создания что б можно было программным способом в любой момент узнать закодированное название зная оригинальное. Как с 16 перевести в 64?

-~{}~ 31.08.10 01:02:

по идее нужно 16 (10 цифр + 6 первых букв) зашифровать с использованием 10 цифр и всех букв в верхнем и нижнем регистре но как?
 

Ярослав

Новичок
kennedy
Если хочешь сохранить оригинальное имя файла то сохраняй его в другом месте, в базе например и потом имя генери айдишник из базы + хеш
 

kennedy

Новичок
не хочется нагружать базу данных. должен же быть какой то алгоритм. или реально ничего не существует?
 

A1x

Новичок
kennedy хранить в базе оригинальное имя и сгенерированный уникальный ключ - это нормальное решение
 

kennedy

Новичок
но все же.
10 цифр + 26х2 = 62 символа

предложите функцию как заменить 16 символов с md5 на 62 (10цифр и 26х2 букв) с целью уменьшения длины.
 

Вурдалак

Продвинутый новичок
Просто вызови N раз mt_rand(0, 61). И длину заодно выберешь.

Конвертирование числа в 62-ричную систему счисления без использования библиотек типа BCMath/GMP ограничивается числами до 2147483647.
 

Alexandre

PHPПенсионер
не могу найди функцию для кодирования в base62. хелп :0
PHP:
    function base62_encode($val, $base=62, $chars='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    // can't handle numbers larger than 2^31-1 = 2147483647
    $str = '';
    do {
        $i = $val % $base;
        $str = $chars[$i] . $str;
        $val = ($val - $i) / $base;
    } while($val > 0);
    return $str;
}
 
    function base62_decode($str, $base=62, $chars='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    $len = strlen($str);
    $val = 0;
    $arr = array_flip(str_split($chars));
    for($i = 0; $i < $len; ++$i) {
        $val += $arr[$str[$i]] * pow($base, $len-$i-1);
    }
    return $val;
}
 

Вурдалак

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

dimagolov

Новичок
у меня есть base62_encode, для произвольной длинны, но только для десятичных чисел, вернее их представления в виде строки в десятичном виде. Тут еще и в base36 есть перевод, для генерации BAR-кодов. Можно допилить для восприятия hex-строк.
п.с. $code это параметр поразрядного сдвига, чтоб враг не догадался, так как кодированные подобным образом данные отправляются в открытом виде.
PHP:
class Math {
	public static function base62_encode ($num, $code= 0) {
		if ($num === '' || !is_bigint($num))
			return FALSE;

    $code= $code < 0 ? -$code : $code;
    $ni= intval($num);
		if ($ni < PHP_INT_MAX)
			return self::base62_encode_int($ni, $code);

		$spliter= 916132832;	// 62 ^ 5
		$parts= self::divide_int($num, $spliter);
		$res= '';
		while ($parts[0] > 0) {
			$cur= self::base62_encode_int(intval($parts[1]), $code);
			while (strlen($cur) < 5)
				$cur= self::base62_encode_int(0, $code).$cur;
			$res= $cur.$res;
			$parts= self::divide_int($parts[0], $spliter);
		}
		return self::base62_encode_int(intval($parts[1]), $code).$res;
	}

	public static function base62_decode ($str, $code= 0) {
    $code= $code < 0 ? -$code : $code;
    $code= $code % 62;
    $ret= 0;
    for ($i= 0, $l= strlen($str); $i < $l; $i++) {
        $cval= ord($str[$i]);
        if (ctype_digit($str[$i]))
            $cval-= ord('0');
        elseif (ctype_upper($str[$i]))
            $cval-= ord('A') - 10;
        elseif (ctype_lower($str[$i]))
            $cval-= ord('a') - 36;
        else
            return -1;
        $val= ($cval >= $code ? 0 : 62) + $cval - $code;
        $ret= self::add62digit($ret, $val);
    }
    return $ret;
	}

	public static function base36_encode ($num, $code= 0) {
		if ($num === '' || !is_bigint($num))
			return FALSE;

    $code= $code < 0 ? -$code : $code;
    $ni= intval($num);
		if ($ni < PHP_INT_MAX)
			return self::base36_encode_int($ni, $code);

		$spliter= 60466176;	// 36 ^ 5
		$parts= self::divide_int($num, $spliter);
		$res= '';
		while ($parts[0] > 0) {
			$cur= self::base36_encode_int(intval($parts[1]), $code);
			while (strlen($cur) < 5)
				$cur= self::base36_encode_int(0, $code).$cur;
			$res= $cur.$res;
			$parts= self::divide_int($parts[0], $spliter);
		}
		return self::base36_encode_int(intval($parts[1]), $code).$res;
	}

	public static function base36_decode ($str, $code= 0) {
    $code= $code < 0 ? -$code : $code;
    $code= $code % 36;
    $ret= 0;
    for ($i= 0, $l= strlen($str); $i < $l; $i++) {
        $cval= ord(strtoupper($str[$i]));
        if (ctype_digit($str[$i]))
            $cval-= ord('0');
        elseif (ctype_upper($str[$i]))
            $cval-= ord('A') - 10;
        else
            return -1;
        $val= ($cval >= $code ? 0 : 36) + $cval - $code;
        $ret= self::add36digit($ret, $val);
    }
    return $ret;
	}

	public static function compare_int($a, $b) {
		if ($a === '' || $b === '' || !is_bigint($a) || !is_bigint($b))
			return FALSE;

		$ai= intval($a);
		$bi= intval($b);
		if ($ai < PHP_INT_MAX && $bi < PHP_INT_MAX)
			return $ai < $bi ? -1 : ($ai > $bi ? 1 : 0);

		$a= ltrim(trim($a, " \t\n\r"), '0');
		$b= ltrim(trim($b, " \t\n\r"), '0');

		$al= strlen($a);
		$bl= strlen($b);
		if ($al < $bl)
			return -1;
		else if ($al > $bl)
			return 1;
		for ($i= 0; $i < $al; $i++) {
			$ai= intval($a[$i]);
			$bi= intval($b[$i]);
			if ($ai < $bi)
				return -1;
			else if ($ai > $bi)
				return 1;
		}
		return 0;
	}

	public static function divide_int ($dividend, $divisor) {
		if ($dividend === '' || $divisor === '' || !is_bigint($dividend) || !is_bigint($divisor))
			return FALSE;

		$dividend= ltrim(trim($dividend, " \t\n\r"), '0');
		$divisor= ltrim(trim($divisor, " \t\n\r"), '0');

		$c= self::compare_int($dividend, $divisor);
		if ($c < 0)
			return array ('0', $dividend);
		else if (!$c)
			return array ('1', '0');

		$res= '';
		$dl= strlen($divisor);
		$cur= substr($dividend, 0, $dl);
		if (intval('9'.$divisor) < PHP_INT_MAX) {
			$divisor= intval($divisor);

			for ($i= 0, $l= strlen($dividend); $i + $dl <= $l; $i++) {
				$d= 0;
				if (intval($cur) >= $divisor) {
					$res.= (string)((int)($cur / $divisor));
					$cur= (string)($cur % $divisor);
				} else
					$res.= '0';
				if ($i + $dl < $l)
					$cur.= $dividend[$i + $dl];
			}
		} else {
			for ($i= 0, $l= strlen($dividend); $i + $dl <= $l; $i++) {
				$d= 0;
				$c= self::compare_int($cur, $divisor);
				while ($c >= 0) {
					for ($j= 0; $j < $dl; $j++) {
						$cl= strlen($cur);
						if ($cur[$cl - $j - 1] >= $divisor[$dl - $j - 1])
							$cur[$cl - $j - 1]= $cur[$cl - $j - 1] - $divisor[$dl - $j - 1];
						else {
							for ($k= $j + 1; $k < $cl; $k++)
								if ($cur[$cl - $k - 1] !== '0') {
									$cur[$cl - $k - 1]= $cur[$cl - $k - 1] - 1;
									break;
								} else
									$cur[$cl - $k - 1]= '9';
							$cur[$cl - $j - 1]= 10 + $cur[$cl - $j - 1] - $divisor[$dl - $j - 1];
						}
					}
					$d++;
					$c= self::compare_int($cur, $divisor);
				}
				$res.= (string)$d;
				if ($i + $dl < $l)
					$cur.= $dividend[$i + $dl];
			}
		}

		$res= ltrim($res, '0');
		$cur= ltrim($cur, '0');
		return array ($res ? $res : '0', $cur ? $cur : '0');
	}

	private static function base62_encode_int ($num, $code= 0) {
    $code= $code < 0 ? -$code : $code;
    $ret= '';
    while ($num >= 0) {
    	$val= $num % 62;
    	$cval= ($val + $code) % 62;
    	if ($cval < 10)
    		$ret.= chr(ord('0') + $cval);
    	elseif ($cval < 36)
    		$ret.= chr(ord('A') + $cval - 10);
    	else
    		$ret.= chr(ord('a') + $cval - 36);
    	if ($num < 62)
    		return strrev($ret);
    	else
    		$num= ($num - $val) / 62;
    }
    return $ret;
	}

	private static function add62digit($num, $val) {
		if (intval($num) <= ((PHP_INT_MAX - 62) / 62))
			return (string)(intval($num) * 62 + intval($val));
	
		$ret= '';
		$num= (string)$num;
		$val= (string)$val;

		for ($i= 0, $cur= 0, $nl= strlen($num), $vl= strlen($val); $i <= $nl; $i++) {
			if ($i < $nl)
				$cur+= $num[$nl - $i - 1] * 2;
			if ($i < $vl)
				$cur+= $val[$vl - $i - 1];
			if ($i)
				$cur+= $num[$nl - $i] * 6;
			$ret= ($cur % 10).$ret;
			$cur= (int)($cur / 10);
		}
	
		if ($cur)
			$ret= $cur.$ret;
		return $ret;
	}

	private static function base36_encode_int ($num, $code= 0) {
    $code= $code < 0 ? -$code : $code;
    $ret= '';
    while ($num >= 0) {
    	$val= $num % 36;
    	$cval= ($val + $code) % 36;
    	if ($cval < 10)
    		$ret.= chr(ord('0') + $cval);
    	else
    		$ret.= chr(ord('A') + $cval - 10);
    	if ($num < 36)
    		return strrev($ret);
    	else
    		$num= ($num - $val) / 36;
    }
    return $ret;
	}

	private static function add36digit($num, $val) {
		if (intval($num) <= ((PHP_INT_MAX - 36) / 36))
			return (string)(intval($num) * 36 + intval($val));
	
		$ret= '';
		$num= (string)$num;
		$val= (string)$val;

		for ($i= 0, $cur= 0, $nl= strlen($num), $vl= strlen($val); $i <= $nl; $i++) {
			if ($i < $nl)
				$cur+= $num[$nl - $i - 1] * 6;
			if ($i < $vl)
				$cur+= $val[$vl - $i - 1];
			if ($i)
				$cur+= $num[$nl - $i] * 3;
			$ret= ($cur % 10).$ret;
			$cur= (int)($cur / 10);
		}
	
		if ($cur)
			$ret= $cur.$ret;
		return $ret;
	}
}
 

A1x

Новичок
такую функцию я использую
работает она странно, но с shuffle в общем случае лучше чем без
PHP:
function makeRandCode($len = 10) {
    static $chr;
    if (empty($chr)) {
        $chr = array_merge(range(0,9),range('a','z'),range('A','Z'));
    }
    shuffle($chr);
    $maxIdx = sizeof($chr) - 1; $code = '';
    for ($i = 0; $i < $len; $i ++) {
        $code .= $chr[rand(0, $maxIdx)];
    }
    return $code;
}
 

ХакИрФсимагущий

[засикречино]
uniqid('',true); на сервере будет уникальным
а зашифровать его md5 можно или чем хотите главное точнвый алгоритм шифрования без дополнительных случайных чисел
 
Сверху