文件系統基本操作類 - 中國WEB開發者網絡 (http://www.webasp.net) -- 技術教程 (http://www.webasp.net/article/) --- 文件系統基本操作類 (http://www.webasp.net/article/9/8983.htm) |
| -- 作者:未知 -- 發佈日期: 2004-05-08 |
| PHP代碼:--------------------------------------------------------------------------------
<?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); } } } ?> |
| webasp.net |