首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 目錄遞迴遍歷與檔案處理類別體系:以移除 UTF-8 BOM 為例

     編輯:PHP 相關知識

檔案系統掃描是許多維護腳本的基礎需求。本文設計 FindFile 基礎遍歷類別與 UnsetBom 繼承實作,展示「模板方法模式」在檔案處理中的應用:基類負責遞迴遍歷與深度控制,子類專注具體檔案處理邏輯。

FindFile 基礎遍歷類別

<?php
class FindFile {
    public $files = [];      // 收集處理過的檔案路徑
    protected $maxdepth = 0; // 0 表示無深度限制

    public function process($spath, $maxdepth = 0) {
        if (is_numeric($maxdepth) && $maxdepth > 0) $this->maxdepth = $maxdepth;
        else $this->maxdepth = 0;
        $this->files = [];
        $this->traversing($spath);
    }

    private function traversing($spath, $depth = 1) {
        if ($handle = opendir($spath)) {
            while (($file = readdir($handle)) !== false) {
                if ($file === '.' || $file === '..') continue;
                $curfile = $spath . '/' . $file;
                if (is_dir($curfile)) {
                    if ($this->maxdepth == 0 || $depth < $this->maxdepth) {
                        $this->traversing($curfile, $depth + 1);
                    }
                } else {
                    $this->handle($curfile); // 模板方法:由子類實作
                }
            }
            closedir($handle);
        }
    }

    protected function handle($file) {
        array_push($this->files, $file); // 預設僅收集路徑
    }
}
?>

UnsetBom 移除 UTF-8 BOM 實作

<?php
class UnsetBom extends FindFile {
    private $filetype = []; // 允許處理的副檔名

    public function __construct($filetype = []) {
        $this->filetype = $filetype;
    }

    protected function handle($file) {
        if ($this->check_ext($file) && $this->check_utf8bom($file)) {
            $this->clear_utf8bom($file);
            array_push($this->files, $file); // 記錄已處理檔案
        }
    }

    private function check_utf8bom($file) {
        $content = file_get_contents($file);
        return strlen($content) >= 3 &&
               ord($content[0]) === 0xEF &&
               ord($content[1]) === 0xBB &&
               ord($content[2]) === 0xBF;
    }

    private function clear_utf8bom($file) {
        $content = file_get_contents($file);
        file_put_contents($file, substr($content, 3)); // 移除前 3 位元組
    }

    private function check_ext($file) {
        $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
        return empty($this->filetype) || in_array($ext, $this->filetype);
    }
}
?>

使用範例

<?php
require 'FindFile.class.php';
require 'UnsetBom.class.php';

$folder = dirname(__FILE__);
$obj = new UnsetBom(['php', 'css', 'js', 'html']); // 指定副檔名
$obj->process($folder); // 掃描當前目錄(無深度限制)
print_r($obj->files);   // 輸出已移除 BOM 的檔案清單

設計模式解析

此結構採用模板方法模式:

  • FindFile::traversing() 定義遍歷骨架(遞迴、深度控制、目錄/檔案判斷)。
  • FindFile::handle() 為抽象操作點(Hook),預設實作為收集路徑。
  • UnsetBom 覆寫 handle() 注入具體業務邏輯(副檔名過濾、BOM 偵測、移除)。

擴充應用範例

1. 程式碼統計行數

class CountLines extends FindFile {
    protected $total = 0;
    protected function handle($file) {
        if ($this->check_ext($file)) {
            $lines = count(file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES));
            $this->total += $lines;
            $this->files[$file] = $lines;
        }
    }
    private function check_ext($file) {
        return in_array(strtolower(pathinfo($file, PATHINFO_EXTENSION)), ['php','js','css','html']);
    }
    public function getTotal() { return $this->total; }
}

2. 關鍵字搜尋

class SearchContent extends FindFile {
    private $keyword;
    public function __construct($keyword, $filetype = []) {
        $this->keyword = $keyword;
        $this->filetype = $filetype;
    }
    protected function handle($file) {
        if ($this->check_ext($file)) {
            $content = file_get_contents($file);
            if (stripos($content, $this->keyword) !== false) {
                $this->files[] = $file;
            }
        }
    }
    private function check_ext($file) {
        return empty($this->filetype) || in_array(strtolower(pathinfo($file, PATHINFO_EXTENSION)), $this->filetype);
    }
}

效能與注意事項

  • file_get_contents 會將整檔讀入記憶體,大檔案(>100MB)建議改用流式讀取 fopen/fgets。
  • 大量檔案(>10萬)遞迴可能觸發記憶體限制,可加入 gc_collect_cycles() 或分批處理。
  • Windows 路徑分隔符統一用 /,PHP 內部自動轉換。
  • 生產環境務必加入權限檢查、例外處理、執行時間限制調整。

這個類別體系展示了如何將「遍歷」與「處理」解耦,新增檔案處理需求時只需繼承 FindFile 並實作 handle(),符合開放封閉原則,極易維護擴充。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved