Страница 1 из 1

[PHP] раскидка файлов по директориям

Добавлено: 2011-11-30 16:28:55
Alex Keda
имеем некоторое количество файлов.
у каждого файла, есть идентификатор - число.
число может быть большим, а пока - это 60k

хочется раскидать не тупо по одноуровневой структуре, когда

Код: Выделить всё

$path = ceil($ID/ 1000) . "/" . $ID . ".bin";
а как-то умней... т.е. многуровневую структуру, с числом файлов на директорию около сотни....

тока вот идей нету =))

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-11-30 17:03:58
ita
а можно предположить сколько файлов будет в итоге?
изменить идентификаторы с 00001 - 60000 на 00000001 - 00060000
структура папок :
000
-00
--00
00.bin
..
99.bin
-01..
путь к файлу получится типа ./000/00/00/01.bin
а алгоритм чтобы так их раскидывать по моему придумать не проблема..

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-11-30 21:13:58
Alex Keda
до 10M, думаю (с расчётом на далёкое-далёкое будущее) - но в этом случае сервер ляжет задолго до этого числа =)
--
проблема как раз в алгоритме

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-01 13:26:20
ita
именование файлов - от 00M до 99M
имя файла - строка, из имени формирутся путь к директории хранения
имена файлов в папках 00-99

Код: Выделить всё

mkdir('/tmp/00/00/01',0755,true);
рекурсивно создаст все необходимые директории

Код: Выделить всё

is_dir('/tmp/00/00/01');
проверит существование директории

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-01 23:11:06
Alex Keda
нихрена не понял

mkdir я пользоваться умею.
имя как создать и путь к директории?

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-02 1:08:47
FiL
я не понял, проблем в чем? разбить число на "двойки"? еденицы-сотни-десятки тысяч-миллионы ?
Так вроде просто.

Код: Выделить всё

$a = floor($ID / 1000000);
$ID = $ID % 1000000;
$b = floor($ID / 10000);
$ID = $ID % 10000;
$c = floor($ID / 100);
$ID = $ID % 100;
$path = $a. "/" . $b . "/" . $c . "/" . $ID . ".bin";
И будет тебе не более 100 записей в каждом каталоге.

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-02 12:34:08
ita
как вариант, превратить число в строку, дополнить нулями если в исходном меньше 8 знаков

Код: Выделить всё

$file = 10;
settype($file;'string');
for($i=0;count($file)<8;$i++)
{
$file .= '0'.$file;
}
дальше создать путь из имени файла, варианты

Код: Выделить всё

$path = substr($file,0,2).'/'.substr($file,2,2).'/'.substr($file,4,2).'/';
#для utf-8 может понадобиться mb_substr, не проверял
#или
$path .= $file[0].$file[1].'/'.$file[2].$file[3].'/'.$file[4].$file[5].'/';


вот рабочий вариант:

Код: Выделить всё

$BasePath = '/tmp/';
$Files = array
(
'00000000',
'00000001',
'00000002',
'10000000',
'10002200',
'10014000',
);
for($i=0;$i<count($Files);$i++)
{
	$Files[$i];
	$FileName = substr($Files[$i],5,2).'.bin';
	$dp = substr($Files[$i],0,6);
	$DirPath = $BasePath.$dp[0].$dp[1].'/'.$dp[2].$dp[3].'/'.$dp[4].$dp[5];
	
	if(!is_dir($DirPath))
	{
	mkdir($DirPath,0755,true);
	}
   #тут можно добавить проверку существования файла и дальше решать что делать если файл существует
	$fr = fopen($DirPath.'/'.$FileName,'w');
	fwrite($fr,'content');
	fclose($fr);
}

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-02 12:47:15
GhOsT_MZ
ita писал(а):как вариант, превратить число в строку, дополнить нулями если в исходном меньше 8 знаков

Код: Выделить всё

$file = 10;
settype($file;'string');
for($i=0;count($file)<8;$i++)
{
$file .= '0'.$file;
}
Лучше так:

Код: Выделить всё

$file = 100;
settype( $file, 'string' );
$file = str_pad( $file, 8 - count( $file ), '0', STR_PAD_LEFT );
Тем более в вашем листинге ошибка, нужно не:

Код: Выделить всё

$file .= '0'.$file;
А:

Код: Выделить всё

$file = '0'.$file;

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-02 12:49:40
ita
2GhOsT_MZ
Согласен, так лучше,и да, виноват,ошибся.

ну и + из такого хранения файлов можно легко получить его изначальный идентификатор

Код: Выделить всё

#$FullFilePath в данном случае будет
# /tmp/00/00/01/00.bin
$BasePath = '/tmp/';
$FileExt = '.bin';
$id=str_replace(array($BasePath,$FileExt,'/'),'',$FullFilePath);
как-то так получается

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-02 12:52:59
GhOsT_MZ
ita писал(а):2GhOsT_MZ
Согласен, так лучше,и да, виноват,ошибся.

ну и + из такого хранения файлов можно легко получить его изначальный идентификатор

Код: Выделить всё

#$FullFilePath в данном случае будет
# /tmp/00/00/01/00.bin
$BasePath = '/tmp/';
$FileExt = '.bin';
$id=str_replace(array($BasePath,$FileExt,'/'),'',$FullFilePath);
как-то так получается
А не быстрее было бы использовать fileinode? И массив склеивать не нужно, а сразу берем скомпилированную функцию и вперед.

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-02 13:14:36
ita
GhOsT_MZ писал(а):А не быстрее было бы использовать fileinode? И массив склеивать не нужно, а сразу берем скомпилированную функцию и вперед.
я предлагал получить не inode файла, а идентификатор из которого изначально формировался путь и имя файла

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-02 13:16:07
Alex Keda
FiL писал(а):я не понял, проблем в чем? разбить число на "двойки"? еденицы-сотни-десятки тысяч-миллионы ?
Так вроде просто.

Код: Выделить всё

$a = floor($ID / 1000000);
$ID = $ID % 1000000;
$b = floor($ID / 10000);
$ID = $ID % 10000;
$c = floor($ID / 100);
$ID = $ID % 100;
$path = $a. "/" . $b . "/" . $c . "/" . $ID . ".bin";
И будет тебе не более 100 записей в каждом каталоге.
вот до этого-то и я сам дошёл...
я думал естьк акой простой алгоритм ...
а не тупо делить, даже без цикла =)

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-02 13:34:20
ita
алгоритм, но снова для строки :)

Код: Выделить всё

$str = '10000000000012321123';
for($i=0;$i<(strlen($str)-2);$i++)
{
	$path .= $str[$i];
	if($i%2==1)
	{
		$path .= '/';
	}
}

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-02 22:06:51
GhOsT_MZ
И снова подправлю, если не против)

Код: Выделить всё

$str = '10000000000012321123';
$length = strlen( $str ) - 2 ;
for( $i = 0; $i <= $length; $i + 2 )
{
   $path .= $str[$i] . $str[$i + 1] . '/';
}
Лаконичней, в 2 раза меньше проходов цикла, длина строки считается один раз, а не при каждом проходе цикла, да и помоему нужно <=, а не <, но тут не уверен, ибо голова уже не варит... Кстати да, количество символов должно быть четным, иначе последний символ отбросится (или будет нотайс, что не есть хорошо, но от него спасет isset), хотя изначально была затея сделать именно четное количество символов, как я понял.
я предлагал получить не inode файла, а идентификатор из которого изначально формировался путь и имя файла
Тогда извиняюсь, тупанул, причем жестко...)

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-03 10:19:09
ita
да по моему тут уже нет смысла оптимизировать по двум причинам:
1.TC уже получил вариант, который его устраивает
2. нет предела совершенству :)

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-03 22:32:44
Alex Keda
устраивает != красиво

а красиво - без уходов в строку, и с любым числом
--
красивого решения, пока не вижу =)
ну да ладно, как верно замечено - совершенству пределов нет

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-04 21:19:40
FiL
Alex Keda писал(а):устраивает != красиво

а красиво - без уходов в строку, и с любым числом
--
красивого решения, пока не вижу =)
ну да ладно, как верно замечено - совершенству пределов нет
а какие проблемы с любым числом и без ухода в строку? Если нет требования, чтоб путь к файлу был одинаковой длины для любого файла, то тоже не проблема.
делишь на 100 (нацело с остатком) пока не получишь 0 и складываешь остатки в в путь. Для мелких $ID путь будет короче. Для больших - длиннее.
Но в каждом каталоге будет не более 100 файлов и 100 подкаталогов. Если это много (200 записей), то дели не на 100, а на 50 :)

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-04 21:42:18
Alex Keda
FiL писал(а):
Alex Keda писал(а):устраивает != красиво

а красиво - без уходов в строку, и с любым числом
--
красивого решения, пока не вижу =)
ну да ладно, как верно замечено - совершенству пределов нет
а какие проблемы с любым числом и без ухода в строку? Если нет требования, чтоб путь к файлу был одинаковой длины для любого файла, то тоже не проблема.
делишь на 100 (нацело с остатком) пока не получишь 0 и складываешь остатки в в путь. Для мелких $ID путь будет короче. Для больших - длиннее.
Но в каждом каталоге будет не более 100 файлов и 100 подкаталогов. Если это много (200 записей), то дели не на 100, а на 50 :)
неполучилось.
запутался в цикле =((

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-04 23:02:33
FiL

Код: Выделить всё

$path = '.bin';
while ($ID > 0) {
 $path = '/' . ($ID % 100) . $path;
 $ID = floor($ID / 100);
}
ну, естественно, потом надо к $path приделать $root какой-то и создать нужные каталоги. Но это таки уже сам.

Re: [PHP] раскидка файлов по директориям

Добавлено: 2011-12-05 12:28:28
Alex Keda
FiL писал(а):

Код: Выделить всё

$path = '.bin';
while ($ID > 0) {
 $path = '/' . ($ID % 100) . $path;
 $ID = floor($ID / 100);
}
ну, естественно, потом надо к $path приделать $root какой-то и создать нужные каталоги. Но это таки уже сам.
во!
в этих двух стркоах я и запутался...

итог:

Код: Выделить всё

function GetFilePath($Table, $ID){
        # директория файлов
        $DirPath = SPrintF('%s/hosts/%s/files/%s',SYSTEM_PATH,HOST_ID,$Table);
        Debug("[root/system/libs/Upload]: DirPath = " . $DirPath);
        # путь к файлу
        $SubDirPath = '';
        $IDa = $ID;
        while ($IDa > 0) {
                $SubDirPath = '/' . ($IDa % 100) . $SubDirPath;
                $IDa = floor($IDa / 100);
        }
        $FileDirPath = $DirPath . $SubDirPath;
        $FilePath = $FileDirPath . "/" . $ID . ".bin";
        Debug("[root/system/libs/Upload]: FilePath = " . $FilePath);

        return Array('FileDir'=>$FileDirPath, 'FilePath'=>$FilePath);
}
правда, пришлось на живой системе перекладывать файлы с одного пути на другой =))