文件系统基本操作类


Posted in PHP onNovember 23, 2006
<?php  
error_reporting(2047);  /*  
* Class IO (SNakeVil 完成 03.25.04) (v1.0.0.0)  
*  
* [说明]  
* 本类用于对文件系统的处理。  
*  
* [功能]  
* **** list_dir($dir_path);  
* 读取指定目录内容,返回内容数组。  
* $dir_path 字符串,指定目录路径  
* 若有错误返回 FALSE,否则返回  
* array(  
* "count"=>array("files","dirs","size"),  
* "list"=>array(  
* array("name","locate","type","size","last_access","last_change","last_modify"),  
* ......  
* )  
* )  
* ********  
* ********  
* **** seek_file($pattern, $dir_path, $seek_type, $sub_dir, $interal, $limit);  
* 根据正则表达式条件,在相应目录及给定层次的子目录中搜索匹配的文件、目录。  
* $pattern 符合 PERL 兼容标准的正则表达式,无须添加 //,系统自行添加  
* $seek_type 有 -1 0 1 三种可能值,0 仅文件夹,1 仅文件,-1 两者都包括  
* $sub_dir 数字值,搜索的子目录深度,指定目录不算,建议不要超过 5  
* $interal 布尔值,为真则返回搜索结果的详细信息,否则只返回文件名、类型及所在目录  
* $limit 数字值,搜索结果限制,避免过度浪费系统资源  
* 若有错误返回 FALSE,否则返回  
* array(  
* array(  
* "name","locate","type"  
* [,"size","last_access","last_change","last_modify"]  
* ),  
* ......  
* )  
* ********  
* ********  
* **** delete($path);  
* 删除指定对象,文件或文件夹——包括内含子目录和文件的非空文件夹。  
* $path 字符串,指定要删除的内容路径,文件或目录均可  
* 如有错误在错误处中断,返回 FALSE,否则返回 TRUE  
* ********  
* ********  
* **** make_dir($path);  
* 建立任意文件夹,相对或绝对路径皆可,深层建立亦可。  
* $path 字符串,要建立的最终目录路径  
* 如有错误返回 FALSE,否则返回 TRUE  
* ********  
* ********  
* **** verify_file($src, $dst, $interal);  
* 使用 MD5 算法比较两个文件是否相同。  
* $src 字符串,源文件路径  
* $dst 字符串,目标文件路径  
* $interal 布尔值,对于大于 1M 文件,可以设置为 FALSE 以省去 MD5 检验步骤,减轻服务器负担  
* 若有错误返回 FALSE,否则返回 TRUE  
* ********  
* ********  
* **** copy($src_path, $dst_path);  
* 对任意文件夹、文件进行复制,相对或绝对路径皆可,文件复制完成后会进行效验,检查是否出错数据错误。  
* $src_path 字符串,指定要复制的源内容路径,文件或目录均可  
* $dst_path 字符串,指定要复制的目标内容路径,文件或目录均可,性质由 $src_path 决定,可为 $src_path 下层目录  
* 若有错误返回 FALSE,否则返回 TRUE  
* ********  
* ********  
* **** move($src_path, $dst_path);  
* 对任意文件夹、文件进行移动,相对或绝对路径皆可,文件移动完成后会进行效验,检查是否出错数据错误。  
* $src_path 字符串,指定要移动的源内容路径,文件或目录均可  
* $dst_path 字符串,指定要移动的目标内容路径,文件或目录均可,性质由 $src_path 决定,可为 $src_path 下层目录  
* 若有错误返回 FALSE,否则返回 TRUE  
*  
* [版权]  
* 风雨明清(SNakeVil@51js, SNakeVil@BU)独立设计完成,保留一切权力。  
* 随意使用,但请勿必保留下面的文本,谢谢!  
*  
* ===========Z=================  
* Class.IO.v1.0.0.0.build040325  
* for.PHP.v4.20+  
* by SNakeVil  
* (snakevil@51js, snakevil@BU)  
* --------+------  
* QQ:118824  
* MSN:snakevil_@hotmail.com  
* HP:<a href="http://www.snakevil.com/" target="_blank">http://www.snakevil.com/</a>  
* ===========Z=================  
*  
*/  
class IO {  
var $error_id;  
var $result;  
var $error_related;  
var $last_exist_dir;  
function IO() {  
$this->result = array();  
$this->error_id = 0x0000;  
$this->error_related = "";  
$this->last_exist_dir = "";  
return $this;  
}  
function error_occur($error_id=0xffff,$error_related="") { // ----0xffff---- 发生错误,但错误原因未知  
if (is_int($error_id)) $this->error_id = $error_id; // 获取错误号  
$this->error_related = $error_related;  
return false; // 错误发生时返回 FALSE 方便进一步处理  
}  
function list_dir($dir_path=".") {  
if (!is_dir($dir_path)) return $this->error_occur(0x0001, $dir_path); // ----0x0001---- 指定目录不存在  
if (!$dir_handle=@opendir($dir_path)) return $this->error_occur(0x0002, $dir_path); // ----0x0002---- 指定目录无权读取  
$result = array(  
"count" => array("files" => 0, "dirs" => 0, "size" => 0),  
"list" => array()  
);  
while (false!==($file_handle=readdir($dir_handle))) { // 使用 !== 防止处理名称为 0 或 FALSE 的文件、目录  
if ($file_handle=="."||$file_handle=="..") continue; // 忽略系统特定的两个文件夹  
$temp = str_replace("\", "/", realpath($dir_path));  
$temp = substr($temp, -1)=="/" ? $temp : $temp."/";  
$temp = array($temp, $file_handle);  
$file_handle = $temp[0].$temp[1]; // 获取绝对地址  
$temp = array(  
"name" => $temp[1],  
"locate" => $temp[0],  
"type" => @filetype($file_handle),  
"size" => filesize($file_handle),  
"last_access" => fileatime($file_handle),  
"last_modify" => filemtime($file_handle),  
"last_change" => filectime($file_handle)  
);  
switch ($temp["type"]) {  
case "file":  
$temp["type"] = 1;  
$result["count"]["files"]++;  
$result["count"]["size"] += $temp["size"];  
break;  
case "dir":  
$temp["type"] = 0;  
$result["count"]["dirs"]++;  
break;  
default: // !!!! 鉴于 Win32 平台,对既非文件也非目录的内容忽略  
$temp["type"] = -1;  
}  
$result["list"][] = $temp;  
}  
closedir($dir_handle);  
unset($dir_handle, $file_handle, $temp);  
clearstatcache(); // 清除文件系统缓存  
return $this->result = $result;  
}  
function seek_file($pattern=".*",$dir_path=".",$seek_type=1,$sub_dir=0,$interal=false,$limit=100) {  
/* 规范一切可能的参数值 */  
$pattern = "/".$pattern."/";  
$seek_type = intval($seek_type);  
$seek_type = $seek_type>0 ? 1 : ($seek_type<0 ? -1 : 0);  
$sub_dir = abs(intval($sub_dir));  
$interal = (bool)$interal;  
$limit = abs(intval($limit));  
if ($limit==0) $limit = 100;  
$sub_dir_list = array(array($dir_path)); // 将查询目录作为子目录层次的第一层来对待  
$result = array();  
/* i 当前处理的子目录层次,0 为指定目录层,即仅处理一个目录 */  
for ($i=0;$i<=$sub_dir;$i++) {  
if (!isset($sub_dir_list[$i])) return $this->result = $result; // 如果某一层子目录没有设置,说明实际目录系统中再无目录,返回  
/* k 每一子目录层次中子目录统计,j 当前处理序号 */  
for ($j=0,$k=count($sub_dir_list[$i]);$j<$k;$j++) { // 根据每一层子目录数量处理  
$l = $this->list_dir($sub_dir_list[$i][$j]);  
if (!$l) return $this->result = $result; // 出现错误,则立即停止返回现有结果  
$l = $l["list"];  
/* n 每一子目录中文件、目录、其他项目统计,m 为当前处理序号 */  
for ($m=0,$n=count($l);$m<$n;$m++) {  
if (count($result)>=$limit) return $this->result = $result; // 如果要求数目已达到,返回  
if ($l[$m]["type"]==0) $sub_dir_list[$i+1][] = $l[$m]["locate"].$l[$m]["name"]; // 搜集下一层子目录信息  
$o = $l[$m]["type"];  
if ($o!=$seek_type&&($seek_type==1||$seek_type==0)) continue; // 忽略不符合要求的项目  
elseif ($o==-1&&$seek_type==-1) continue;  
if (!preg_match($pattern, $l[$m]["name"])) continue; // 忽略不符合正则表达式的项目  
$result[] = $interal ? $l[$m] : array("name" => $l[$m]["name"], "locate" => $l[$m]["locate"], "type" => $l[$m]["type"]);  
}  
}  
}  
unset($i, $j, $k, $l, $m, $n, $o, $sub_dir_list);  
return $this->result = $result;  
}  
function delete($path="") {  
if (!file_exists($path)) return $this->error_occur(0x0003, $path); // ----0x0003---- 指定对象不存在  
if (is_dir($path)) {  
$path = str_replace("", "/", realpath($path));  
$path = substr($path, -1)=="/" ? $path : $path."/";  
$sub_list = array(array($path));  
for ($i=0;$i<count($sub_list);$i++) { // 使用 COUNT($SUB_LIST) 动态判断长度,从而有可能无定长循环  
if (!isset($sub_list[$i])) break; // 探索到最尽头,获得该目录下所有子目录列表,方便文件删除后删除目录  
for ($j=0,$k=count($sub_list[$i]);$j<$k;$j++) {  
$l = $this->list_dir($sub_list[$i][$j]);  
if (!$l) return $this->error_occur("", $sub_list[$i][$j]);  
$l = $l["list"];  
for ($m=0,$n=count($l);$m<$n;$m++) {  
$o = $l[$m]["locate"].$l[$m]["name"];  
if ($l[$m]["type"]==0) $sub_list[$i+1][] = $o;  
elseif (!@unlink($o)) return $this->error_occur(0x0004, $o); // 删除目录下的每一个文件  
}  
}  
}  
for($i=count($sub_list)-1;$i>=0;$i--) // 逆回删除目录  
for ($j=0,$k=count($sub_list[$i]);$j<$k;$j++) // 删除每一个子目录直到指定目录  
if (!@rmdir($sub_list[$i][$j])) return $this->error_occur(0x0005, $sub_list[$i][$j]); // ----0x0005---- 目录无权删除  
unset($i, $j, $k, $l, $m, $n, $o, $sub_list);  
return true;  
} elseif (@unlink($path)) return true;  
else return $this->error_occur(0x0004, $path); // ----0x0004---- 文件无权删除  
}  
function generate_realpath($path="") {  
if ($path==""||!is_string($path)) return $this->error_occur(0x0007, $path); // ----0x0007---- 路径参数错误  
$path = preg_replace("/(?<!^w)[:*?"<>|]/", "", str_replace("\", "/", $path)); // 规范路径中多可能性的符号  
if (substr($path,1,1)==":") return $path; // !!!! Win32 平台的绝对路径  
elseif (substr($path,0,1)=="/") return substr(realpath("."), 0, 2).$path; // !!!! Win32 平台下的绝对路径转换  
else {  
if (substr($path,-1)=="/") $path = substr($path,0,-1); // 清除结尾可能的 / 符号  
$path = preg_replace("//{2,}/", "/", $path); // 将 /// 诸如类似的相连符号简化为一个  
$path = explode("/", $path); // 分割路径  
$cur_path = explode("/", str_replace("\", "/", realpath(".")));  
for ($i=0,$j=count($path);$i<$j;$i++) {  
if ($path[$i]=="..") array_pop($cur_path);  
elseif ($path[$i]=="."||$path[$i]==str_repeat(".", strlen($path[$i]))) continue; // 忽略无用的相对路径地址 . 和 .... 等  
else array_push($cur_path, $path[$i]);  
}  
$path = implode("/", $cur_path);  
unset($cur_path);  
return $path;  
}  
}  
function make_dir($path="") {  
if (!$path=$this->generate_realpath($path)) return false;  
$path = explode("/", $path);  
$i = array($path[0]);  
for ($i=0,$j=count($path),$k=array(),$l="";$i<$j;$i++) {  
array_push($k, $path[$i]);  
$l = implode("/", $k);  
if (!file_exists($l)) {  
if ($this->last_exist_dir=="") $this->last_exist_dir = $l;  
if (!@mkdir($l)) return $this->error_occur(0x0008, $l); // ----0x0008---- 无法创建目录  
}  
}  
return true;  
}  
function verify_file($src="",$dst="",$interal=true) {  
if (!file_exists($src)||!is_file($src)) return $this->error_occur(0x000A, $src); // ----0x000A---- 指定对象非文件  
if (!file_exists($dst)||!is_file($dst)) return $this->error_occur(0x000A, $dst);  
$i = filesize($src);  
if ($i!=filesize($dst)) {  
unset($i);  
return false;  
}  
if ($i>1024*1024*1024&&!$interal) { // 对于大于 1MB 的文件,如果不要求精确检查,跳过  
unset($i);  
return true;  
}  
unset($i);  
if (md5_file($src)!=md5_file($dst)) return false;  
return true;  
}  
function copy($src_path="",$dst_path="") {  
if (!file_exists($src_path)) return $this->error_occur(0x0003, $src_path);  
if (!$dst_path=$this->generate_realpath($dst_path)) return false;  
if (is_dir($src_path)) {  
$this->last_exist_dir = ""; // 记录现行实际存在的目录  
if (!$this->make_dir($dst_path)) return false; // 建立目录失败  
$src_path = str_replace("", "/", realpath($src_path));  
$src_path = substr($src_path, -1)=="/" ? $src_path : $src_path."/";  
$sub_list = array(array($src_path));  
for ($i=0;$i<count($sub_list);$i++) {  
if (!isset($sub_list[$i])) break;  
for ($j=0,$k=count($sub_list[$i]);$j<$k;$j++) {  
$l = $this->list_dir($sub_list[$i][$j]);  
if (!$l) return $this->error_occur(0x0003, $sub_list[$i][$j]);  
$l = $l["list"];  
for ($m=0,$n=count($l);$m<$n;$m++) {  
$o = $l[$m]["locate"].$l[$m]["name"];  
if ($o==$this->last_exist_dir) continue; // 如果为上级目录向下级目录复制,防止死循环  
$p = str_replace(substr($src_path, 0, -1), $dst_path, $o);  
if ($l[$m]["type"]==0) {  
$sub_list[$i+1][] = $o;  
if (!$this->make_dir($p)) return false; // 对每一个子目录都予以建立  
} else { // 对每一个文件进行复制  
if ($this->verify_file($o, $p)) continue; // 如果目标与源完全相同,不再复制  
if (!copy($o,$p)||!$this->verify_file($o,$p)) return $this->error_occur(0x0009, $o); // ----0x0009---- 文件移动失败  
}  
}  
}  
}  
unset($i, $j, $k, $l, $m, $n, $o, $p, $sub_list);  
return true;  
} else {  
if (!is_readable($src_path)) return $this->error_occur(0x0006, $src_path); // ----0x0006---- 源文件无权读取  
if ($this->verify_file($src_path,$dst_path)) return true;  
$i = strrpos($dst_path, "/");  
$dst_path = array(substr($dst_path, 0, $i), substr($dst_path, $i+1));  
unset($i);  
if (!$this->make_dir($dst_path[0])) return false;  
$dst_path = implode("/", $dst_path);  
if (!copy($src_path,$dst_path)||!$this->verify_file($src_path,$dst_path)) return $this->error_occur(0x0009, $src_path);  
return true;  
}  
}  
function move($src_path="",$dst_path="") {  
if (!file_exists($src_path)) return $this->error_occur(0x0003, $src_path);  
if (!$dst_path=$this->generate_realpath($dst_path)) return false;  
if (is_dir($src_path)) {  
$this->last_exist_dir = "";  
if (!$this->make_dir($dst_path)) return false;  
$src_path = str_replace("", "/", realpath($src_path));  
$src_path = substr($src_path, -1)=="/" ? $src_path : $src_path."/";  
$sub_list = array(array($src_path));  
for ($i=0;$i<count($sub_list);$i++) {  
if (!isset($sub_list[$i])) break;  
for ($j=0,$k=count($sub_list[$i]);$j<$k;$j++) {  
$l = $this->list_dir($sub_list[$i][$j]);  
if (!$l) return $this->error_occur(0x0003, $sub_list[$i][$j]);  
$l = $l["list"];  
for ($m=0,$n=count($l);$m<$n;$m++) {  
$o = $l[$m]["locate"].$l[$m]["name"];  
if ($o==$this->last_exist_dir) continue;  
$p = str_replace(substr($src_path, 0, -1), $dst_path, $o);  
if ($l[$m]["type"]==0) {  
$sub_list[$i+1][] = $o;  
if (!$this->make_dir($p)) return false;  
} else {  
if ($this->verify_file($o, $p)) continue;  
if (!copy($o,$p)||!$this->verify_file($o,$p)) return $this->error_occur(0x0009, $o);  
if (!@unlink($o)) return $this->error_occur(0x0004, $o);  
}  
}  
}  
}  
for($i=count($sub_list)-1;$i>=0;$i--)  
for ($j=0,$k=count($sub_list[$i]);$j<$k;$j++)  
if (strpos($this->last_exist_dir,$sub_list[$i][$j])!==false) continue; // 对移动目标目录的上层目录,不予考虑删除  
elseif (!@rmdir($sub_list[$i][$j])) return $this->error_occur(0x0005, $sub_list[$i][$j]);  
unset($i, $j, $k, $l, $m, $n, $o, $p, $sub_list);  
return true;  
} else {  
if (!is_readable($src_path)) return $this->error_occur(0x0006, $src_path);  
if ($this->verify_file($src_path,$dst_path)) return true;  
$i = strrpos($dst_path, "/");  
$dst_path = array(substr($dst_path, 0, $i), substr($dst_path, $i+1));  
unset($i);  
if (!$this->make_dir($dst_path[0])) return false;  
$dst_path = implode("/", $dst_path);  
if (!copy($src_path,$dst_path)||!$this->verify_file($src_path,$dst_path)) return $this->error_occur(0x0009, $src_path);  
if (@unlink($src_path)) return true;  
else return $this->error_occur(0x0004, $src_path);  
}  
}  
}  
?>
PHP 相关文章推荐
php 数学运算验证码实现代码
Oct 11 PHP
提高PHP编程效率的53个要点(经验小结)
Sep 04 PHP
php各种编码集详解和以及在什么情况下进行使用
Sep 11 PHP
php获取中文拼音首字母类和函数分享
Apr 24 PHP
php数组中包含中文的排序方法
Jun 03 PHP
php+ajax实时输入自动搜索匹配的方法
Dec 26 PHP
PHP中error_log()函数的使用方法
Jan 20 PHP
php微信开发之百度天气预报
Nov 18 PHP
php删除数组指定元素实现代码
May 03 PHP
PHP基于MySQLI函数封装的数据库连接工具类【定义与用法】
Aug 11 PHP
Laravel5.5新特性之友好报错以及展示详解
Aug 13 PHP
PHP常用正则表达式精选(推荐)
May 28 PHP
header()函数使用说明
Nov 23 #PHP
如何使用脚本模仿登陆过程
Nov 22 #PHP
php5 and xml示例
Nov 22 #PHP
PHP中的类-什么叫类
Nov 20 #PHP
解决phpmyadmin 乱码,支持gb2312和utf-8
Nov 20 #PHP
PHP配置心得包含MYSQL5乱码解决
Nov 20 #PHP
PHP+MySQL5.0中文乱码解决方法
Nov 20 #PHP
You might like
PHP中的类-什么叫类
2006/11/20 PHP
PHP 将图片按创建时间进行分类存储的实现代码
2010/01/05 PHP
ThinkPHP3.1新特性之G方法的使用
2014/06/19 PHP
谈谈你对Zend SAPIs(Zend SAPI Internals)的理解
2015/11/10 PHP
让ThinkPHP的模板引擎达到最佳效率的方法详解
2017/03/14 PHP
jquery JSON的解析方式
2009/07/25 Javascript
Extjs学习笔记之七 布局
2010/01/08 Javascript
js读取配置文件自写
2014/02/11 Javascript
JavaScript的作用域和块级作用域概念理解
2014/09/21 Javascript
javascript实现禁止鼠标滚轮事件
2015/07/24 Javascript
jquery树形菜单效果的简单实例
2016/06/06 Javascript
深入剖析Express cookie-parser中间件实现示例
2018/02/01 Javascript
axios 处理 302 状态码的解决方法
2018/04/10 Javascript
echarts同一页面中四个图表切换的js数据交互方法示例
2018/07/03 Javascript
vue-router判断页面未登录自动跳转到登录页的方法示例
2018/11/04 Javascript
[00:09]DOTA2新版本PA至宝特效动作展示
2014/11/19 DOTA
[01:34]2016国际邀请赛中国区预选赛IG战队教练采访
2016/06/27 DOTA
Pandas读取MySQL数据到DataFrame的方法
2018/07/25 Python
Python实现繁?转为简体的方法示例
2018/12/18 Python
Python自定义一个异常类的方法
2019/06/27 Python
python opencv 读取图片 返回图片某像素点的b,g,r值的实现方法
2019/07/03 Python
python处理excel绘制雷达图
2019/10/18 Python
Tensorflow 实现释放内存
2020/02/03 Python
Python绘制全球疫情变化地图的实例代码
2020/04/20 Python
Yankee Candle官网:美国最畅销蜡烛品牌之一
2020/01/05 全球购物
Scotch Porter官方网站:男士美容产品
2020/08/31 全球购物
澳洲的UGG雪地靴超级市场:Uggs.com.au
2020/04/06 全球购物
一套VC试题
2015/01/23 面试题
关于递归的一道.NET面试题
2013/05/12 面试题
证券期货行业个人的自我评价
2013/12/26 职场文书
餐厅执行经理岗位职责范本
2014/02/26 职场文书
售后服务承诺书怎么写
2014/05/21 职场文书
购房意向书
2014/08/30 职场文书
写给同学的新学期寄语
2015/02/27 职场文书
JS的深浅复制详细
2021/10/16 Javascript
vue3.0 数字翻牌组件的使用方法详解
2022/04/20 Vue.js