Posted: Tue Mar 18, 2003 10:48 pm (написано за 23 минуты 11 секунд)
Post subject: Файловые функции
В этой теме уже достаточно долгое время я выкладываю свои функции для работы с файлами, которых нет в стандартной поставке PHP, и многие из которых написаны с применением рекурсии, которая немного сложна для понимания новичками.
Функции, которые здесь представлены:
1) show_size($f,$format=true,$size=false) - показывает размер папки или файла $f, если $format=true или не указан, то вместо размера в байтах, возвращается строка, содержащая уже отформатированный размер - например не «10253», а «10.01 Kb». Как показывает практика, это более удобно, так как всё равно обычно приходится приводить всё к такому виду. Если указан третий параметр ($size), то функция просто оформляет указанный размер в виде "XX Kb" или "XX Mb", и т.д.
2) display_perms($f) - показывает права файла или папки $f в виде «drwxrwxrwx». ИМХО это наиболее естественное и удобное представление прав файлов и папок.
3) get_owner($file), get_group($file) - показывают соответственно владельца или группу *nix файла или папки $file. В Windows возвращается пустая строка.
4) remove_u($dir) - удаляет файл или папку $dir (папка может и не быть пустой). Постфикс «_u» у функций обозначает «universal» - универсальный, не зависящий от того, папка это или файл, работающий всегда.
5) chmoddir($dir,$mod) - выставляет права $mod папке $dir всем вложенным папкам и файлам
6) copy_u($src,$dest) - копирует папку или файл $src в указанное место $dest. Заметьте, что, естественно, в качестве $dest нужно указывать не папку, в которую нужно скопировать $src, а папку, которая должна в результате этого получиться. То же самое касается и файлов.
7) writefile(), file2string() и dirstats() - читайте описание функций, они не так часто используются, но описание на русском языке.
Извиняюсь за то, что некоторые комментарии на английском языке, что функции, вообще говоря, написаны в разном стиле и т.д... Они все писались в разное время и даже разными людьми, все проверены и отлажены, пользуйтесь наздоровье. Любые комментарии, дополнения и критика крайне приветствуется. Спасибо за внимание.
/** * Shows size of $f file or folder like "1023.53 Kb". If $format=false, it returns just filesize in bytes. If $size is not false, the function will just format $size value, but not count the size of directory again. * * @param string $f * @param bool $format * @return string/int */ function show_size($f,$format=true,$size=false) { if($format || $size!==false) { if($size===false)$size=show_size($f,false); $p = ''; if($size<=1024)return$p.$size.' bytes'; elseif($size<=1048576)return$p.round($size/1024,2).' Kb'; elseif($size<=1073741824)return$p.round($size/1048576,2).' Mb'; elseif($size<=1099511627776)return$p.round($size/1073741824,2).' Gb'; elseif($size<=1125899906842624)return$p.round($size/1099511627776,2).' Tb'; elsereturn$p.round($size/1125899906842624,2).' Pb'; }else { if(is_file($f))returnsprintf("%u",filesize($f)); // for files the size of which is more than 2 Gb and less than 4 Gb $size=0; $dh=opendir($f); while(($file=readdir($dh))!==false) { if($file=='.' || $file=='..') continue;
/** * Function grabbed from PhpRemoteView and was a bit improved. Returns string, file permissions like -rwxr-xrw- * Example of usage: display_perms("file") * * @param string $f * @return string */ function display_perms($f) { // global $_SERVER; // if ($_SERVER['COMSPEC']) return "<i>Windows-система</i>"; /* Determine Type */ $mode=fileperms($f);
# chmoddir ( string dir, int mod ) # dir - папка, права которой нужно сменить (желательно абсолютный путь) # # комментарий - функция меняет права всем вложенным папкам и файлам внутри папки # # возвращает true в случае удачи и false, если сменить права папке не удалось function chmoddir($dir, $mod) { $dh=opendir($dir); while(false!==($file=readdir($dh))) { if($file!="." && $file!="..") { $fullpath=$dir."/".$file; if(!is_dir($fullpath)) { if(!@chmod($fullpath, $mod))exec('chmod '.$mod.' '.$fullpath); }else { chmoddir($fullpath, $mod); } } } closedir($dh); if(!@chmod($dir, $mod) || exec('chmod '.$mod.' '.$dir)) { returntrue; }else { returnfalse; } }
/** * Copy not only files, but folders too. See copy() description for details * * @param string $src * @param string $dest * @return bool */ function copy_u($src,$dest) { if(!file_exists($src))returnfalse; if(is_file($src))returncopy($src,$dest);
# writefile ( string file, string content ) # file - файл, который нужно переписать # content - содежимое файла # # возвращает true в случае удачи и false в случае, когда файл не может быть переписан
function writefile($file, $content) { if(is_readable($file) && is_writable($file)) { $f=fopen($file,"wb+"); //обязательно wb , просто w портит бинарные файлы fputs($f,$content); fclose($f); returntrue; }else { returnfalse; } }
# file2string ( string file ) # file - файл, содержимое которого нужно получить # # возвращает содержимое файла в случае удачи, и false в противном случае
# mkfile ( string name [, int mod] ) # name - имя создаваемого файла # [mod] - (необязательный параметр) права файла после создания # # возвращает true в случае удачи и false, когда файл создать не удалось
# dirstats ( string dir ) # dir - папка, статистику которой нужно получить # # возвращает массив из трех элементов: # files - количество файлов # dirs - количество папок # size - общий размер папки
// ищет файл. // рекурсивно обходит каталоги, начиная с $basedir и возвращает реальный путь к файлу, // или false, если ничего не найдено. // ! возвращает путь к первому найденному файлу ! function getfname ($fname,$basedir="/"){ $res = false; $dr = $_SERVER['DOCUMENT_ROOT']; $f = $dr.$basedir.$fname; if(file_exists($f) && is_file($f))return$f; if($dir = opendir($dr.$basedir)){ while(false !== ($entry = readdir($dir))){ if($entry != "." && $entry != ".." && is_dir($dr.$basedir."/".$entry)){ $res = getfname ($fname, $basedir.$entry."/"); } if($res)break; } closedir($dir); } return$res; }
// Удаляет каталог, все подкаталоги и файлы. // пути считаются от корня сайта. function removedir($dir){ $dr = $_SERVER['DOCUMENT_ROOT']."/"; $dh = opendir($dr.$dir); while(false !== ($file = readdir($dh))){ if($file != "." && $file != ".."){ $fullpath = $dr.$dir."/".$file; if(!is_dir($fullpath)){ unlink($fullpath); }else{ removedir($dir."/".$file); } } } closedir($dh); returnrmdir($dr.$dir); }
// перемещает файлы из $s в $d, на перемещаемые // директории устанавливаются права $m // все директории создаются относительно корня сайта. function move($s,$d,$m=0777){ $dr = $_SERVER['DOCUMENT_ROOT']."/"; makedir ($d,$m); $dh = opendir($dr.$s); while(false !== ($file = @readdir($dh))){ if($file != "." && $file != ".."){ $fullpath = $dr.$s."/".$file; if(!is_dir($fullpath)){ copy($fullpath,$dr.$d."/".$file); }else{ move($s."/".$file,$d."/".$file); } } } closedir($dh); removedir($s); }
// создает директорию и все предшествующие директории. // на все создаваемые директории устанавливаются права $m // директории создаются начиная с корня сайта. function makedir ($d,$m=0777){ $dr = $_SERVER['DOCUMENT_ROOT']; $dir = explode("/",$d); $d = "/".$dir[0]; for($i=1;$i<count($dir);$i++){ $d .= "/".$dir[$i]; if(!file_exists($dr.$d)){ mkdir($dr.$d,$m); @chmod($dr.$d,$m); } } }
// создает файл и все предшествующие ему директории. // устанавливает всем права $m function mkfile ($f,$m=0777){ $dr = $_SERVER['DOCUMENT_ROOT']."/"; makedir (dirname($f),$m); $p = fopen($dr.$f,"a"); fwrite($p,""); fclose($p); @chmod($dr.$f,$m); }
WingedFox: Полторы !?!?! Функция removedir и mkfile !!! В общем-то неважно, что mkfile создает и директории (хотя не должен), которые появляются "на пути" к этому файлу, и что removedir удаляет все файлы и папки относительно "корня сайта".
Ими пользуются те, кто любит экономить свое время =) Сейчас вовсю пользуюсь getfname() - тормозов нет вообще, а удобства - море. Уже даже не вспоминаю про запрещение некоторых хостеров на работу с относительными путями, на работу сайта в подкаталоге... 8*)
Posted: Thu Jul 31, 2003 11:53 am (спустя 1 час 30 минут)
Post subject:
Евгений Бондарев: Да что Вы говорите !!! Я еще слышал от Дмитрия Котерова про функцию dirname() - кстати говоря лучше даже, чем realpath, как оказалось ;). Я использую абсолютные пути, но эти пути не привязаны жестко, это "относительные абсолютные пути" - можно так сказать.
Евгений Бондарев: Абсолютно согласен с предыдущим оратором :) А этот самый realpath() не поможет уже даже при простом переносе файла в другой каталог :)
Евгений Бондарев: realpath - хорошо, действительно помогает, но все равно не всегда. dirname лучше. Когда include файла делаешь, который находится в другой директории, а тот инклюдит другой файл... Ну и короче говоря во всей этой путанице dirname(__FILE__) очень даже помогает.
Евгений Бондарев: Ну, все правильно. Ведь директория обычно "." ? А dirname(__FILE__) выдает то же самое, что и realpath("."), но realpath не учитывает, что этот файл может быть заинклюден из другой папки, и "." - это адрес не той папки, в которой находится скрипт, которого инклюдили, а той, в которой находится скрипт, который инклюдил. А dirname(__FILE__) всегда выдает правильный путь. В общем, наверное мы говорим о разных вещах.
Posted: Wed Sep 10, 2003 12:51 pm (спустя 14 дней 2 часа 47 минут)
Post subject: Дерево каталогов.
Хотелось бы увидеть какой-нибудь скрипт, выводящий полное дерево каталогов (включая файлы) сайта. Я думаю, что он пригодится для создания "карты сайта". Самому в лень с этим заниматся, а вот если вы начнете давать идеи... Может что-нибудь решим. Заранее благодарен.
Хотелось бы увидеть какой-нибудь скрипт, выводящий полное дерево каталогов (включая файлы) сайта. Я думаю, что он пригодится для создания "карты сайта". Самому в лень с этим заниматся, а вот если вы начнете давать идеи... Может что-нибудь решим. Заранее благодарен.
Читай книгу Дмитрия Котерова. Я на основе примера из этой книги создал карту сайта (ну естественно с дополнениями, там можно создавать, редактировать, удалять, переименовывать каталоги и файлы. В общем позволяет работать с содержимым сайта через браузер при отсутствии доступа по FTP. Но начал-то я её делать полностью переписав пример из книги. Сейчас даже страницу скажу: глава 16, страница 271, так и называется "Пример:печать дкерева каталогов"
# chmoddir ( string dir, int mod ) # dir - папка, права которой нужно сменить (желательно абсолютный путь) # # комментарий - функция меняет права всем вложенным папкам и файлам внутри папки # # возвращает true в случае удачи и false, если сменить права папке не удалось function chmoddir($dir, $mod) { $dh=opendir($dir); while($file=readdir($dh)) { if($file!="." && $file!="..") { $fullpath=$dir."/".$file; if(!is_dir($fullpath)) { if(!@chmod($fullpath, $mod))exec('chmod '.$mod.' '.$fullpath); }else { chmoddir($fullpath, $mod); } } } closedir($dh); if(!@chmod($dir, $mod) || exec('chmod '.$mod.' '.$dir)) { returntrue; }else { returnfalse; } }
Last edited by WingedFox on Tue Mar 07, 2006 11:19 pm; edited 1 time in total
/* get permissions of file $f. If $oct is set to false, it will return the string like "drwxrwxrwx" instead of returning something like 777 */ function get_rights($file, $oct=true, $p=false) { static$s='rwxrwxrwx',$t='upcudubu-ulusuwu';
Posted: Fri Apr 27, 2007 4:34 pm (спустя 34 минуты; написано за 48 секунд)
Post subject:
Юpий Насрeтдинов wrote:
18 Марта 2003
Кажется, тогда был только PHP 4.2, в котором функции file_get_contents не присутствовало. К тому же, file_get_contents() на больших объёмах(вроде 30 Мб) валится. По крайней мере, валился.
<? define('MAX_COPY_TIME',7); // how many seconds the files can be copied $__copy_cache = array('dirs' => array(/* 0 => array(from, to, offset) */), 'files' => array());
/* $fromlist - list with absolute paths of files and folders you want to copy. $tolist - list of files you want to get after copying */ function advanced_copy_start($fromlist, $tolist) { global$__copy_cache; foreach($fromlistas$k=>$v) { $__copy_cache[is_dir($v) ? 'dirs' : 'files'][] = array($v, $tolist[$k], 0); } returntrue; }
/* gets cache if $cache is not set returns cache otherwise */
if(!$res) continue; /* we will just skip anything we cannot copy... it's good behavour, by the way */ if(!file_exists($dir[1]) && !mkdir($dir[1],0777)) continue;
Posted: Sun Dec 09, 2007 10:45 pm (спустя 6 месяцев 28 дней 21 час 6 минут; написано за 7 минут 47 секунд)
Post subject:
Если Вам нужно в своей админ-панели (или где-то ещё) отображать сортированный список файлов, можно воспользоваться следующей функцией, которая способна отдавать список файлов (с разделением на страницы) за очень короткое время. На сервере с моим файловым менеджером открытие папки с 50000 файлов занимает всего-лишь 0.7 сек (для сравнения, PhpRemoteView и другим требуется то же время для открытия папки с 1000 файлов). Функция поддерживает сортировку по любым доступным полям stat(), а также по имени файла и по его правам.
Если используется сортировка по любому полю, кроме имени, работа существенно замедляется из-за необходимости вызвать stat() для каждого файла в директории. Такая поддержка всё равно присутствует, причём реализация сортировки также в несколько раз производительнее аналогов. Новичкам функция может быть полезна в плане обучения использованию array_multisort() :).
field1, ..., fieldN -- requested fields (default 'name' and 'size') $list1, ..., $listN -- a list of values (array('value1', 'value2', ...,'valueN')),
$pagemin and $pagemax -- the page numbers of the specified range (default 1) pages_num -- filtered number of pages (returns 1 if you do not ask not to split to pages) items_num -- filtered number of files + total number of folders
function d_filelist_extreme($dir, $params=array()) { /* set defaults: $key = ''; is equal to default value for $params['key'] */
$fields = array('name', 'size'); // name, chmod or any field of stat(): (size, mtime, uid, gid, ...)
$filt=''; // filename filter $sort='name'; // what field to sort (see $fields) $order='asc'; // sorting order: "asc" (ascending) or "desc" (descending)
$fast=true; // use some optimizations (e.g. can allow to get some range from a filelist of 5000 files in 0.1 sec) $maxit=200; // how many items is enough to enable optimization?
$split=true; // split result to pages and return only results for pages from $pagemin to $pagemax (including both) $pagemin=1; $pagemax=1; // see description for $split $perpage=30; // how many files per page
// the function to log errors. If $error_text is set to 'all', the function returns an array of all error messages. // If $error_text is not set, the function returns the last error message. if $error_text==NODEBUG, the name of function will be removed if it was present (in the beginning) // Else it logs the error message and returns false. // // example of usage: if(false) return d_error('You have set "false" in "if" condition'); define('NODEBUG',1); function d_error($error_text = 0) { static$errors = array();
Posted: Sun Dec 09, 2007 11:20 pm (спустя 35 минут; написано за 1 минуту 37 секунд)
Post subject:
К вопросу о том, зачем такая функция нужна, отвечу: очень приятно, когда все папки открываются без задержек, даже если количество файлов в папке огромно и достигает нескольких тысяч (большинство файловых менеджеров, даже не web-based, начинают ощутимо тормозить на таких объёмах).
Posted: Wed Dec 12, 2007 2:08 pm (спустя 2 дня 14 часов 48 минут; написано за 1 минуту 25 секунд)
Post subject:
Интересно, неужели я сам все эти 15000 просмотров набил :)? Господа, скажите, хоть кто-нибудь из этих 15000 просмотревших обратил внимание на семество функций advanced_copy_*() и на новую d_filelist_extreme()?
Posted: Thu Dec 13, 2007 9:01 pm (спустя 1 день 6 часов 52 минуты; написано за 11 минут 49 секунд)
Post subject:
Используем возможности PHP и JavaScript ещё более полно:
Семейство функций multipart_*() -- продолжение идей, которые были заложены в функции advanced_copy_*() -- копированию файлов в несколько приёмов.
Функции multipart_*() позволяют делать вообще любые операции с файлами, которые Вам нужны, в несколько приёмов с сохранением промежуточного состояния. Это может понадобиться, если вы хотите посчитать объём какой-нибудь огромной папки, скопировать большой массив файлов, или даже удалить большую папку. Юзвери -- существа нетерпеливые, поэтому если состояние операции не будет показываться, то они вряд ли будут от этого сильно счастливы.
/* * function, that begins multipart operation * * PARAMS: array $params * * array $params -- see possible keys in the beginning of function * * RETURN: * * array $cache -- an array (you should not know it's structure) with data * for multipart_cont() */
function multipart_begin($params) { $files = array(); // initial array of files & folders to process $data = array(); // any information your functions may need to run $basedir = isset($_SESSION['DIR']) ? $_SESSION['DIR'] : getcwd();
/* $processors is array of function names to process file * ($filename -- name of file or directory):
begin($filename, $data)
'begin' is name of function to start processing file. function must return FALSE on failure and $resumedata array for cont() or TRUE if you will not use cont(), with cont() being a continue function described below.
the next two are not obligatory:
cont($filename, $data, $resumedata):
function that continues the processing (should not work too long), it should return TRUE on successfull finish, FALSE on error and $resumedata array for temporary information, which is saved between multipart_cont() calls. If function does not need resume data, please return empty array instead of something else (because of strict comparison with bool TRUE and FALSE in multipart_cont() ).
stop($filename, $data, $successful):
function to be executed on successful (or not) end of operation */
'files' => $files, /* files left for processing */
'curfile' => false, /* the name of processed file, if script was stopped at cont() function */ 'resume_data' => array(), ); }
/* * function to continue the processing of files * * PARAMS: $cache -- obligatory parameter with function cache * * RETURN: * * TRUE on success (process finished successfully) * FALSE on error * array $cache if operation is to be continued */
function multipart_cont($cache) { if(is_bool($cache))return$cache; /* this line should be here */
/* * first symbol filename of $files will tell, what to do with file: * * i -- intermediate file, which needs continue processing (w/$resume_data) * n -- new file with unknown type: use all actions * d -- directory which should not be expanded, just execute processors * (needed for $dircall = 'after' and 'before') */
if(!@chdir($basedir))return d_error('cannot change directory to current');
if(is_file($name) || $a == 'd' || $a == 'i')/*only execute processors*/ { /* for intermediate files we already have $resume_data from cache */ /* TODO: do not just skip errors at begin function */ if($a != 'i' && ($resume_data=$b($name, $data)) === false) continue;
if($c) { $have = true; /* for case when $resume_data = true */ $curfile = $name;
/* * we just get a list of files (even without determining type) * because stat() (or is_file() or is_dir()) consumes much time. * it is important if directory is huge (5000-50000 files) */
// the function to log errors. If $error_text is set to 'all', the function returns an array of all error messages. // If $error_text is not set, the function returns the last error message. if $error_text==NODEBUG, the name of function will be removed if it was present (in the beginning) // Else it logs the error message and returns false. // // example of usage: if(false) return d_error('You have set "false" in "if" condition'); define('NODEBUG',1); function d_error($error_text = 0) { static$errors = array();
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.