/**
* @]クラス名[= IO
* @]クラスURI[= System.IO
* @]目的[=
* このクラスはファイルシステムの処理に使用されます
* @]著者[= SNakeVil (snakevil@qq.com)
* @]バージョン[= 1.1.1
* @]作成[= 17:13 2004-3-25
* @]修正[=
]* 2004-3-30 4:04 「
」* +generate_path()メソッドのいくつかのバグを修正
* +メソッドno_comment()を再設計
* 2004-3-29 4:32
* + list_dir() メソッドの戻り値を簡略化 [
* + ファイルまたはディレクトリの情報を取得するメソッド file_info() を追加します
* 2004-3-28 5:35
* + 最適化アルゴリズムを整理する
* 2004-3-27 7:31
* + 基本クラス pB への抽象エラー処理
* + ファイル内のC仕様コメントを削除するメソッドno_comment()を追加
* @]参照[=
*/
クラスIOはSnkClassを拡張します
var $result; //メソッドの戻り値が混在している場合は、成功した演算結果をここで取得できます
var $exec_cmd; //実行メソッド、まだ適用されていません
var $exist_dir; // ディレクトリ作成時に存在していた最後のディレクトリ。現在は copy() と move() に使用されます
var $buffer_size; // ファイル読み取りバッファー サイズ。サービス アプリケーションの規模とサーバー構成に応じて変更されます。デフォルト値が推奨されます
関数IO()
parent::SnkClass();
$this->result = array();
$this->exec_cmd = "";
$this->exist_dir = "";
$this->buffer_size = 8192;
$this を返す;
}
/**
* @]メソッド名[= list_dir()
* @]目的[=
* 指定されたディレクトリの内容を読み取り、内容の配列を返します
* @]パラメータ[=
* string $dir_path はディレクトリパスを指定します。デフォルトは現在のディレクトリです
* @]Return[=mixed エラーの場合は FALSE を返し、それ以外の場合は
を返します*array(
* array("名前","場所","種類"),
*……
*)
* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/
関数 list_dir($path=".")
if (!is_dir($path)) return $this->error_occur(0x000B, __FUNCTION__);
if (!is_readable($path)) return $this->error_occur(0x0002, $path);
$dh = @opendir($path);
$result = array();
$path = realpath($path);
if ($path[strlen($path)-1]!=DIRECTORY_SEPARATOR) $path .= DIRECTORY_SEPARATOR // ディレクトリの絶対アドレスの後のディレクトリ区切り文字を確認します
while (FALSE!==($fh=readdir($dh))) { // 名前が 0 または FALSE のファイルとディレクトリが処理されないようにするには、!== を使用します
if ($fh=="."||$fh=="..") // システム固有のフォルダーを無視します
;$i = $path.$fh; // 絶対アドレスを取得します
;$t = array(
「名前」 => $fh, V u,
「場所」 => $i,
"type" => is_file($i) ? 1 : (is_dir($i) ? 0 : -1)
);
$result[] = $t;
}
closedir($dh);
unset($dh, $fh, $t, $i);
clearstatcache(); // ファイルシステムのキャッシュをクリアします
return $this->result = $result;
}
/**
* @]メソッド名[= file_info()
* @]目的[=
* 指定されたファイルまたはディレクトリの属性を取得します
* @]パラメータ[=
* string $dir_path はディレクトリパスを指定します。デフォルトは現在のディレクトリです
* @]Return[=mixed エラーの場合は FALSE を返し、それ以外の場合は
を返します* array("名前","場所","タイプ","サイズ","アクセス","変更","変更","読み取り","書き込み"),
* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/
関数 file_info($path=".")
$path = realpath($path);
if (!$path) return $this->error_occur(0x000A, __FUNCTION__);
$result = array(
"name" => substr($path, strrpos($path, DIRECTORY_SEPARATOR)+1),
"場所" => $path, FHH C,~|5
"type" => is_file($path) ? 1 : (is_dir($path) ? 0 : -1),
"サイズ" => ファイルサイズ($path),
"access" => fileatime($path),
"変更" => filemtime($path),
"change" => filectime($path),
"read" => is_readable($path),
"write" => is_writeable($path)
);
clearstatcache();
return $this->result = $result;
}
/**
* @]メソッド名[= Seek file()
* @]目的[=
* 正規表現の条件に基づいて、指定されたレベルの対応するディレクトリおよびサブディレクトリ内で一致するファイルとディレクトリを検索します
* @]パラメータ[=
* string $pattern は、検索一致要件を指定する PERL 標準正規表現と互換性があり、/^ $/ が追加され、デフォルトは .*
です。* string $path 検索用のディレクトリパス、デフォルトは現在のパスです
* enum $seesk_type には 3 つの値があります -1 0 1、0 はフォルダーのみ、1 はファイルのみ、-1 には両方が含まれ、デフォルトは 1 です
* int $sub_dir サブディレクトリの深さを検索します。指定されたディレクトリはカウントされません。5 を超えないようにすることをお勧めします。デフォルトは
*システムリソースの過剰な浪費を避けるために $limit 検索結果の制限を制限します。デフォルトは 100 です
* @]Return[= 混合エラーは FALSE を返し、それ以外の場合は
*array(
*array(
*「名前」、「場所」、「種類」
* )、
*……
*)
* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/
関数seek_file($pattern=".*", $path=".", $seek_type=1, $sub_dir_level=0, $limit=100)
/* パラメータ値を確認 */
$is_error = $seek_type!=1 && $seek_type!=0 && $seek_type!=-1;
$is_error = $is_error && (!is_int($sub_dir_level) || $sub_dir_level < 0);
$is_error = $is_error && (!is_int($limit) || $limit < 1);
if ($is_error) return $this->error_occur(0x000B, __FUNCTION__);
unset($is_error);
$result = array();
/* array() == FALSE なので、 === */
を使用する必要がありますif (FALSE===$i=$this->list_dir($path)) return FALSE // ディレクトリをリストできない場合は、戻ります
;for ($j=0,$k=count($i);$j
if ($i[$j]["type"]==-1) continue; // ディレクトリ項目およびファイル項目以外の場合はスキップします。
if ($i[$j]["type"]==0&&$sub_dir_level) { // 下位ディレクトリを検索する必要がある場合if (FALSE===$l=$this->seek_file($pattern,$i[$j]["location"],$seek_type,($sub_dir_level - 1),$limit)) return FALSE;
$result = array_merge($result, $l) // 下位ディレクトリの検索結果を追加します
}
if ($seek_type+$i[$j]["type"]==1||!preg_match("/^".$pattern."$/", $i[$j]["name"])) continue; // 現在の型が検索されない場合はスキップします
$result[] = $i[$j];
if (count($result)>=$limit) { //要件を超えた長さを切り捨ててリストを残す
array_splice($result, $limit);
休憩;
}
}
unset($i, $j, $k, $l);
return $this->result = $result;
}
/**
* @]メソッド名[= delete()
* @]目的[=
* 指定されたオブジェクト、ファイル、またはフォルダーを削除します - サブディレクトリやファイルを含む空ではないフォルダーも含みます
* @]パラメータ[=
* string $path は、削除するコンテンツのパス (ファイルまたはディレクトリ) を指定します
* @]Return[= ブール値はエラーの場合は FALSE を返し、それ以外の場合は TRUE を返します
* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/
関数削除($path="") {
$path = realpath($path);
if (!$path) return $this->error_occur(0x000A, __FUNCTION__);
if (!is_dir($path)) {
if (@unlink($path)) return TRUE // ファイルは正常に削除されました
;
Return $this->error_occur(0x0004, $path);} 他 {
if (FALSE===$i=$this->list_dir($path)) return FALSE
;
for ($j=0,$k=count($i);$j if (!$this->delete($i[$j]["location"])) return FALSE; // ディレクトリの内容の削除エラー;
unset($i, $j, $k);TRUE を返します;
}
}
/**
* @]メソッド名[=generate_path() =l
* @]目的[=
* 既存または存在しないファイルとディレクトリの絶対アドレスを取得します
* @]パラメータ[=
* string $path アドレスを取得したいファイルまたはディレクトリが既存の相対アドレスまたは絶対アドレスです
* @]Return[= string 取得したアドレス
* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/
関数generate_path($path="") {
$i = "/"==DIRECTORY_SEPARATOR ? "\" : "/"; // 統合されたディレクトリ区切り文字
$path = str_replace($i, DIRECTORY_SEPARATOR, strval($path));
if ($path[strlen($path)-1]!=DIRECTORY_SEPARATOR) $path .= DIRECTORY_SEPARATOR;
$i = strpos($path, DIRECTORY_SEPARATOR) // パス内の最初のディレクトリ区切り文字の位置を取得します
$ext = substr($path, $i+1);
$path = substr($path, 0, $i+1);
if ($i=realpath($path)) $path = $i // 基本パスを取得します
;その他 {
$ext = $path.$ext;
$path = realpath(".");
}
if (strlen($ext)) { // 残りのコンテンツを処理します
$ext = preg_replace("/[:*?"<>|]/", "",explode(DIRECTORY_SEPARATOR, $ext));
array_pop($ext);
$path =explode(DIRECTORY_SEPARATOR, $path) // ディレクトリ層軸を作成します
;if ($path[count($path)-1]=="") array_pop($path);
while (count($ext)) {
$i = array_shift($ext);
if ($i==".."&&count($path)>1) array_pop($path);
elseif (""!=str_replace(".", "", $i)) $path[] = $i;
}
$path = implode(DIRECTORY_SEPARATOR, $path);
}
unset($ext, $i);
$path を返す;
}
/**
* @]メソッド名[= make_dir()
* @]目的[=
*相対パスまたは絶対パス、または深い作成のいずれかで任意のフォルダーを作成します
* @]パラメータ[=
* string $path 作成される最終ディレクトリパス
* @]Return[= ブール値はエラーの場合は FALSE を返し、それ以外の場合は TRUE を返します
* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/ )
関数 make_dir($path="") {
$i =explode(DIRECTORY_SEPARATOR, $this->generate_path($path)); // ディレクトリパスを生成します
$path = array_shift($i);
for ($j=0,$k=count($i);$j
$path .= DIRECTORY_SEPARATOR.$i[$j];
if (!is_dir($path)) {
if ($this->exist_dir=="") $this->exist_dir = $path; // 最後の既存ディレクトリのパスを記録します
if (!@mkdir($path)) return $this->error_occur(0x0003, substr($path, 0, strrpos($path, DIRECTORY_SEPARATOR)));
}
}
if ($this->exist_dir=="") $this->exist_dir = $path;
TRUE を返します;
}
/**
* @]メソッド名[= verify_file()
* @]目的[=
* MD5アルゴリズムを使用して、2つのファイルが同じかどうかを比較します
* @]パラメータ[=
* string $src ソースファイルパス
* string $dst ターゲットファイルパス
* boolean $internal 1MBを超えるファイルの場合は、FALSEを設定するとMD5検証ステップが省略され、サーバーの負担が軽減されます
* @]Return[= ブール値はエラーの場合は FALSE を返し、それ以外の場合は TRUE を返します
* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/
関数 verify_file($src="", $dst="", $internal=TRUE) {
if (!is_file($src)||!is_file($dst)) return $this->error_occur(0x000B, __FUNCTION__);
if (!is_readable($src)) return $this->error_occur(0x0006, $src);
if (!is_readable($dst)) return $this->error_occur(0x0006, $dst);
$i = ファイルサイズ($src);
if (filesize($dst)!=$i) { // ファイルサイズは異なります
設定解除($i);
FALSEを返す;
}
if ($i>1024*1024*1024&&!$internal) { // 1MB ファイルの場合、正確なチェックが必要ない場合はスキップします
設定解除($i);
TRUE を返します;
}
設定解除($i);
if (md5_file($src)!=md5_file($dst)) return FALSE; // ファイルの MD5 検証が満たされておらず、内容が異なります
;TRUE を返します;
}
/**
* @]メソッド名[= copy()
* @]目的[=
* 相対パスまたは絶対パスで任意のフォルダーまたはファイルをコピーします。 ファイルのコピーが完了すると、エラーやデータエラーがないかどうかが検証されます。
* @]パラメータ[=* string $src_path は、コピーするソースコンテンツのパス (ファイルまたはディレクトリ) を指定します
* string $dst_path は、コピーするターゲットのコンテンツのパスを指定します。これは、ファイルまたはディレクトリにすることができます。その性質は、$src_path によって決まります。これは、$src_path の下位レベルのディレクトリにすることができます
。
* @]Return[= ブール値はエラーの場合は FALSE を返し、それ以外の場合は TRUE を返します* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/
関数 copy($src="", $dst="", $sub=FALSE) {
if (!$src=realpath($src)) return $this->error_occur(0x000B, __FUNCTION__);
$dst = $this->generate_path($dst);
if (is_dir($src)) { // 処理ディレクトリ
/*
*アルゴリズムの説明:
* 当初、神に会うときに神と悪魔を殺すために非常に単純な再帰アルゴリズムを使用する予定でしたが、後で問題が見つかりました。
* ソースパスの子孫パスの場合はどうするか? このようにして、アルゴリズムは検出を続けます...* したがって、この場合、ターゲットパスの既存の部分を記録するために $this->exist_dir 属性が追加されました。新しい質問です
* 次に問題は、この属性をどのように保存するかということです。
* 関数全体を $this->copy() メソッドに統合し、この関数に記録する必要があります
* は変化するため、各操作での変化を防ぐための別の効果的な方法が必要です。
* 回避策として、隠しパラメーター $sub を使用します。アルゴリズムが変更されない限り、このパラメーターは常にパラメーター リストの先頭に表示されます。
※後者です。したがって、メソッドは不安定になり始めますが、それを行う方法はありません。プログラマー自身が意図的にそれを壊さないことを祈るだけです。
※外部呼び出しの場合、デフォルトがFALSEなので、$this->exist_dirと書きます。内部再帰中に明示的に TRUE、
* この属性は有効であることが保証されています。
*/
if (!is_readable($src)) return $this->error_occur(0x0002, $src);
if ($dst[strlen($dst)-1]!=DIRECTORY_SEPARATOR) $dst .= DIRECTORY_SEPARATOR;
if (TRUE===$sub&&$src==$this->exist_dir) return TRUE; // ソースパスは記録されたターゲットパスです
;if (TRUE!==$sub) $this->exist_dir = "" // ディレクトリを作成する前に、ターゲットディレクトリパスに存在するディレクトリパスを記録します
;if (!$this->make_dir($dst)) return FALSE
;if (FALSE===$i=$this->list_dir($src)) return FALSE; // ディレクトリの読み取りエラー
;for ($j=0,$k=count($i);$jcopy($i[$j]["location"], $dst) .$i[$j]["名前"],TRUE)) FALSE を返します;
unset($i, $j, $k);
TRUE を返す;
} 他 {
if (!is_readable($src)) return $this->error_occur(0x0006, $src);
if ($this->verify_file($src,$dst)) return TRUE;
if (!copy($src,$dst)) return $this->error_occur(0x0007, $dst);
if (!$this->verify_file($src,$dst)) {
@unlink($dst); // ファイルのコピーと新しいファイルの削除に失敗しました
return $this->error_occur(0x0007, $dst);
}
TRUE を返します;
}
}
/**
* @]メソッド名[= move()
* @]目的[=
* 相対パスまたは絶対パスで任意のフォルダーまたはファイルを移動します。ファイルの移動が完了すると、エラーやデータエラーがないかどうかが検証されます www.hidianying.cn
。* @]パラメータ[=
* string $src_path は、移動するソースコンテンツのパス (ファイルまたはディレクトリ) を指定します
* string $dst_path は、移動するターゲットのコンテンツ パスを指定します。これは、ファイルまたはディレクトリにすることができます。性質は、$src_path によって決まります。これは、$src_path の下位ディレクトリにすることができます
。* @]Return[= ブール値はエラーの場合は FALSE を返し、それ以外の場合は TRUE を返します
* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/
関数 move($src="", $dst="", $sub=FALSE) {
if (!$src=realpath($src)) return $this->error_occur(0x000B, __FUNCTION__);
$dst = $this->generate_path($dst);
if (is_dir($src)) { // 処理ディレクトリ
if (!is_readable($src)) return $this->error_occur(0x0002, $src);
if ($dst[strlen($dst)-1]!=DIRECTORY_SEPARATOR) $dst .= DIRECTORY_SEPARATOR;
if (TRUE===$sub&&$src==$this->exist_dir) return TRUE;
if (TRUE!==$sub) $this->exist_dir = "";
if (!$this->make_dir($dst)) return FALSE;
if (FALSE===$i=$this->list_dir($src)) return FALSE;
for ($j=0,$k=count($i);$jmove($i[$j]["location"], $dst) .$i[$j]["名前"],TRUE)) FALSE を返します;
unset($i, $j, $k);
if (FALSE===strpos($this->exist_dir,$src))
if (!@rmdir($src)) return $this->error_occur(0x0004, $src); // 対象外ディレクトリの上位ディレクトリについては削除
TRUE を返します;
} 他 {
if (!is_readable($src)) return $this->error_occur(0x0006, $src);
if ($this->verify_file($src,$dst)) return TRUE;
if (!copy($src,$dst)) return $this->error_occur(0x0007, $dst);
if (!$this->verify_file($src,$dst)) {M
@unlink($dst);
Return $this->error_occur(0x0007, $dst);
}
if (!@unlink($src)) return $this->error_occur(0x0006, $src); // ソースファイルを削除します
TRUE を返します;
}
}
/**
* @]メソッド名[= no_comment()
* @]目的[=
* ファイル内の C 仕様のコメントをクリアします
//このチュートリアルは 97xxoo Tutorial Network (www.97xxoo.org) から提供されており、完全なチュートリアルを表示するには、http://www.97xxoo.org/article/1/2008/20081018053.shtml をクリックしてください。
* @]パラメータ[=* string $path は操作を実行するファイルを指定します
* @]Return[= ブール値はエラーの場合は FALSE を返し、それ以外の場合は TRUE を返します
* @]著者[= SNakeVil (snakevil@qq.com)
* @]参照[=
*/
関数 no_comment($path="") {
if (!is_file($path)) return $this->error_occur(0x000B, __FUNCTION__);
if (!is_readable($path)) return $this->error_occur(0x0006, $path);
if (!is_writeable($path)) return $this->error_occur(0x0007, $path);
if (!$th=tmpfile()) return $this->error_occur(0x000C, $path); // 一時ファイルを作成します
$fh = fopen($path, "r+b");
if (!flock($fh,LOCK_EX)) { // ファイルをロック
fclose($fh);
設定解除($fh);
Return $this->error_occur(0x0009, $path);
}
$fbuffer = fread($fh, $this->buffer_size*2) // ファイル読み込みバッファ
;
$tbuffer = "" // 一時ファイルバッファ; $in_dq = $in_sq = $in_lc = $in_bc = FALSE;while ($fblen=strlen($fbuffer)) { // 生データを処理します
$fstats = feof($fh);
for ($i=0;$i<$fblen;$i++) { // ファイルの内容を分析します
if (!$fstats&&$i+5>$fblen) Break; // ファイルが完全に読み込まれていない場合、バッファ近くのファイルコンテンツの次のブロックを読み取って読み込みを完了します
$j = substr($fbuffer, $i, 2);
$k = $j[0];
if ($j=="/*"&&!$in_dq&&!$in_sq&&!$in_lc) { // 文字列コメントや行コメントではなく、ブロックコメントが始まります
$in_bc = TRUE;
$i++;
} elseif ($j=="*/"&&$in_bc) { // ブロックコメントの終わり
$in_bc = FALSE;
$i+=2;
} elseif ($j=="//"&&!$in_dq&&!$in_sq&&!$in_bc) { // 行コメントが始まります
$in_lc = TRUE;
$i++;
} elseif ($in_lc&&($k=="r"||$k=="n")) $in_lc = FALSE; // 行末コメント
;
elseif ($j=="\\"||$j=="\""||$j=="\'") { // エスケープ文字 )$tbuffer .= $j;
$i++;
続きます;
} elseif ($k=="""&&!$in_sq&&!$in_bc&&!$in_lc) $in_dq = !$in_dq; // 二重引用符の文字列の開始と終了
elseif ($k=="'"&&!$in_dq&&!$in_bc&&!$in_lc) $in_sq = !$in_sq // 一重引用符の文字列の開始と終了
if ($in_lc||$in_bc) continue; // コメントでは、
をスキップします。
$tbuffer .= $fbuffer[$i];}
$fbuffer = substr($fbuffer, $i) // 読み込んだ部分を破棄します
;
unset($i, $j, $k);if (!$fstats) $fbuffer .= fread($fh, $this->buffer_size);
if ($fstats||strlen($tbuffer)>=$this->buffer_size) { // 正当なデータを一時ファイルに書き込みます
if (!fwrite($th,$tbuffer)) { // 容量不足のため書き込みに失敗しました
fclose($th);
flock($fh, LOCK_UN);
fclose($fh);
unset($th, $fh, $in_dq, $in_sq, $in_lc, $in_bc, $i, $j, $k);
$this->error_occur(0x000D, "");
を返す
}$tbuffer = "";
}
}
unset($fbuffer, $tbuffer, $fstats, $in_dq, $in_sq, $in_lc, $in_bc);
rewind($fh); // ファイルポインタをファイルの先頭に戻します
巻き戻し($th);
$i = $j = "";
$k = 0;
while (!feof($th)) { // 一時ファイルのデータをソースファイルに書き戻す
$i = fgets($th, $this->buffer_size);
if ($j=="") { // ファイルシステムの改行文字を取得します
$j= substr($i, -2);
if ($j=="rn")
elseif ($j[1]=="r"||$j[1]=="n")
$k = 1;
$j = $j[1];
} else $j = "";
}
if (substr($i, -$k)==$j) {
$i = rtrim(substr($i, 0, -$k), " t");
if (strlen($i)) fwrite($fh, $i.$j) // 正しいスペースをクリアします
;
それ以外の場合は続行します;} else fwrite($fh, rtrim($i, " t"));
}
ffflush($fh); // ファイルを保存して閉じます
ftruncate($fh, ftell($fh));
fclose($th);
flock($fh, LOCK_UN);
fclose($fh);
unset($i, $j, $k, $fh, $th);
TRUE を返します;
}
}
/**
* @]エラーリスト[=
* 0x0001 指定されたディレクトリは存在しません
* 0x0002 指定されたディレクトリには読み取り権限がありません
* 0x0003 指定されたディレクトリには書き込み権限がありません
* 0x0004 指定されたディレクトリには削除権限がありません
* 0x0005 指定されたファイルは存在しません
* 0x0006 指定されたファイルには読み取り権限がありません
* 0x0007 指定されたファイルには書き込み権限がありません
* 0x0008 指定されたファイルには削除権限がありません
* 0x0009 指定されたファイルをロックできません
* 0x000A 指定されたオブジェクトは存在しません
* 0x000B メソッドで指定したパラメータが間違っています
* 0x000C 一時ファイルを作成できません
* 0x000D ディスク容量が不足しています
* 0x000E
*0x000F
* 0x0010
* 0x0011
*
*/
?>
)