文件系统基本操作类

代码如下:

<?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); 



?>

(0)

相关推荐

  • 文件系统基本操作类

    复制代码 代码如下: <?php  error_reporting(2047); /*  * Class IO (SNakeVil 完成 03.25.04) (v1.0.0.0)  *  * [说明]  * 本类用于对文件系统的处理.  *  * [功能]  * **** list_dir($dir_path);  * 读取指定目录内容,返回内容数组.  * $dir_path 字符串,指定目录路径  * 若有错误返回 FALSE,否则返回  * array(  * "count"

  • C# 文件安全管理需要注意的

    在实际的项目开发中,我们经常需要使用到文件的I/O操作,主要包含对文件的增改删查等操作,这些基本的操作我们都是很熟悉,但是较少的人去考虑文件的安全和操作的管理等方面,例如文件的访问权限管理,文件数据的彻底删除和数据的恢复等等,这一系列的操作需要我们对.NET的相关知识有一个深刻的学习. 在本文章主要介绍文件和目录的一些基本操作,以及文件目录的权限和安全设置的相关内容. 一.DotNet文件目录常用操作: 提到文件的I/O操作,这个对于每一个开发者来说都不是陌生的事,因为这些操作是我们在项目开发过

  • Java输入输出流的使用详细介绍

    1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读写数据的标准方法.任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法. Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO. 流IO的好处是简单易用,缺点是效率较低.块IO效率很高,但编程比较

  • 浅谈Spring的两种配置容器

    Spring提供了两种容器类型 SpringIOC容器是一个IOC Service Provider.提供了两种容器类型:BeanFactory和ApplicationContext.Spring的IOC容器是一个提供IOC支持的轻量级容器.除了基本的ioc支持,它作为轻量级容器还提供了IOC之外的支持. BeanFactory BeanFactory是基础类型IOC容器.顾名思义,就是生产Bean的工厂.能够提供完整的IOC服务.没有特殊指定的话,其默认采用延迟初始化策略.只有当客户端对象需要

  • ASP.NET Core全面扫盲贴

    1. 前言 .NET发行至今已经过了十四个年头.随着版本的不断迭代更新,.NET在Windows平台上的表现也是越来越好,可以说Windows平台上所有的应用类型.NET几乎都能完成. 只是成也Windows,败也Windows,这十四年来,除了部分"民间"版本,.NET一直没能在官方支持下摆脱Windows平台的局限,"开源"和"跨平台"这两个词语也是所有.NET开发者心中的痛楚.最终,.NET Core出现了,它让开发者们在官方和社区的支持走

  • Android仿今日头条APP实现下拉导航选择菜单效果

    本文实例为大家分享了在Android中如何实现下拉导航选择菜单效果的全过程,供大家参考,具体内容如下 关于下拉导航选择菜单效果在新闻客户端中用的比较多,当然也可以用在其他的项目中,这样可以很方便的选择更多的菜单.我们可以让我们的应用顶部有左右滑动或进行切换的导航菜单,也可以为了增强用户体验在应用中添加这样的下拉导航选择菜单效果. 关于它的实现原理,其实也是挺简单的,就是使用PopupWindow来进行展现,在显示时控制其高度并配置以相应的动画效果.在PopupWindow中我使用GridView

  • 全面解析Node.js 8 重要功能和修复

    5月30日12点,Node.js 8正式发布了,这个版本具有一系列新功能和性能改进,并且这些功能和改进将获得长期支持(LTS). 下面就来介绍Node.js 8版本中最重要的功能和修复. 新版本的代号是Carbon.Node.js 8将从2017年10月起,正式成为当前的LTS版本,并持续到2019年12月31日.这也意味着Node.js 6版本将在2018年4月进入到维护模式,并在2019年4月结束维护支持. 下载Node.js 8版本:https://nodejs.org/download/

  • Java 面试题和答案 - (下)

    第一篇讨论了面向对象编程和它的特点,关于Java和它的功能的常见问题,Java的集合类,垃圾收集器,本章主要讨论异常处理,Java小应用程序,Swing,JDBC,远程方法调用(RMI),Servlet和JSP. 异常处理 Java小应用程序(Applet) Swing JDBC 远程方法调用(RMI) Servlet JSP 异常处理 43.Java中的两种异常类型是什么?他们有什么区别? Java中有两种异常:受检查的(checked)异常和不受检查的(unchecked)异常.不受检查的异

  • 浅谈SpringBoot之开启数据库迁移的FlyWay使用

    本文介绍了SpringBoot开启数据库迁移的FlyWay使用,分享给大家,具体如下: 一,首先我先了解下FlyWay是如何运转的. 最简单的方案是将Flyway指向一个空数据库. 它将尝试找到其元数据表.当数据库为空时,Flyway将不会找到它, 而是创建它.您现在拥有一个名为SCHEMA_VERSION的单个空表的数据库 : 该表将用于跟踪数据库的状态.之后,Flyway将开始扫描应用程序的文件系统或类路径进行迁移.它们可以用Sql或Java编写. 然后根据其版本号对迁移进行排序,并按顺序应

  • SpringBoot 配置提示功能(超详细)

    目的 配置自动提示的辅助功能可以让配置写起来更快,准确率大大提高. springboot jar 包含提供所有支持的配置属性细节的元数据文件.文件的目的是为了让 IDE 开发者在用户使用 application.properties 或 application.yml 文件时提供上下文帮助和代码补全. 大多数元数据文件是在编译时通过处理用 @ConfigurationProperties 注释的所有项自动生成的.也可以手动编写部分元数据. 版本 参考 SpringBoot 2.2.0.RELEA

随机推荐