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

PHP 文件與目錄操作工具類 FileUtil:創建、刪除、移動、複製全功能封裝與調用示例

     編輯:PHP 相關知識

PHP 文件與目錄操作工具類 FileUtil:創建、刪除、移動、複製全功能封裝與調用示例

原生文件系統函數分散、參數不一、缺乏遞歸支持。本文提供一個生產就緒的 FileUtil 靜態工具類,封裝創建、刪除、移動、複製四大核心操作,支持遞歸目錄處理、覆蓋控制、錯誤抑制與鏈式調用。

FileUtil 完整源碼

<?php
/**
 * 文件系統統一操作工具類
 * 
 * 用法示例:
 * FileUtil::createDir('a/1/2/3');              // 遞歸創建目錄
 * FileUtil::createFile('b/1/2/3.exe');         // 創建文件 (自動創建父目錄)
 * FileUtil::copyDir('b', 'd/e');               // 遞歸複製目錄
 * FileUtil::copyFile('b/1/2/3.exe', 'b/b/3.exe');
 * FileUtil::moveDir('a/', 'b/c');              // 遞歸移動目錄
 * FileUtil::moveFile('b/1/2/3.exe', 'b/d/3.exe');
 * FileUtil::unlinkFile('b/d/3.exe');           // 刪除文件
 * FileUtil::unlinkDir('d');                    // 遞歸刪除目錄
 */
class FileUtil {
    /** 統一路徑分隔符為 DIRECTORY_SEPARATOR */
    private static function normalize($path) {
        return str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path);
    }

    /** 確保目錄存在,不存在則遞歸創建 */
    private static function ensureDir($path) {
        $path = self::normalize($path);
        if (!is_dir($path)) {
            return mkdir($path, 0755, true);
        }
        return true;
    }

    // ==================== 創建操作 ====================

    /** 創建目錄 (遞歸) */
    public static function createDir($aimUrl) {
        return self::ensureDir(self::normalize($aimUrl));
    }

    /** 創建文件 (自動創建父目錄)
     * @param bool $overWrite 是否覆蓋已存在文件
     */
    public static function createFile($aimUrl, $overWrite = false) {
        $aimUrl = self::normalize($aimUrl);
        if (file_exists($aimUrl)) {
            if (!$overWrite) return false;
            self::unlinkFile($aimUrl);
        }
        self::ensureDir(dirname($aimUrl));
        return touch($aimUrl);
    }

    // ==================== 刪除操作 ====================

    /** 刪除文件 */
    public static function unlinkFile($aimUrl) {
        $aimUrl = self::normalize($aimUrl);
        if (file_exists($aimUrl) && is_file($aimUrl)) {
            return @unlink($aimUrl);
        }
        return false;
    }

    /** 遞歸刪除目錄 (包含所有子文件/子目錄) */
    public static function unlinkDir($aimDir) {
        $aimDir = self::normalize($aimDir);
        if (!is_dir($aimDir)) return false;

        $items = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($aimDir, RecursiveDirectoryIterator::SKIP_DOTS),
            RecursiveIteratorIterator::CHILD_FIRST
        );
        foreach ($items as $item) {
            $item->isDir() ? @rmdir($item->getPathname()) : @unlink($item->getPathname());
        }
        return @rmdir($aimDir);
    }

    // ==================== 複製操作 ====================

    /** 複製文件 */
    public static function copyFile($fileUrl, $aimUrl, $overWrite = false) {
        $fileUrl = self::normalize($fileUrl);
        $aimUrl  = self::normalize($aimUrl);

        if (!file_exists($fileUrl) || !is_file($fileUrl)) return false;
        if (file_exists($aimUrl) && !$overWrite) return false;
        if (file_exists($aimUrl) && $overWrite) self::unlinkFile($aimUrl);

        self::ensureDir(dirname($aimUrl));
        return copy($fileUrl, $aimUrl);
    }

    /** 遞歸複製目錄 */
    public static function copyDir($oldDir, $aimDir, $overWrite = false) {
        $oldDir = self::normalize($oldDir);
        $aimDir = self::normalize($aimDir);

        if (!is_dir($oldDir)) return false;
        self::ensureDir($aimDir);

        $items = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($oldDir, RecursiveDirectoryIterator::SKIP_DOTS),
            RecursiveIteratorIterator::SELF_FIRST
        );
        foreach ($items as $item) {
            $target = $aimDir . DIRECTORY_SEPARATOR . $items->getSubPathname();
            if ($item->isDir()) {
                self::ensureDir($target);
            } else {
                self::copyFile($item->getPathname(), $target, $overWrite);
            }
        }
        return true;
    }

    // ==================== 移動操作 ====================

    /** 移動文件 (跨目錄即為移動,同目錄即為重命名) */
    public static function moveFile($fileUrl, $aimUrl, $overWrite = false) {
        $fileUrl = self::normalize($fileUrl);
        $aimUrl  = self::normalize($aimUrl);

        if (!file_exists($fileUrl)) return false;
        if (file_exists($aimUrl) && !$overWrite) return false;
        if (file_exists($aimUrl) && $overWrite) self::unlinkFile($aimUrl);

        self::ensureDir(dirname($aimUrl));
        return rename($fileUrl, $aimUrl);
    }

    /** 遞歸移動目錄 */
    public static function moveDir($oldDir, $aimDir, $overWrite = false) {
        $oldDir = self::normalize($oldDir);
        $aimDir = self::normalize($aimDir);

        if (!is_dir($oldDir)) return false;
        self::ensureDir($aimDir);

        // 先複製再刪除源目錄 (跨文件系統安全)
        if (self::copyDir($oldDir, $aimDir, $overWrite)) {
            return self::unlinkDir($oldDir);
        }
        return false;
    }
}

兩種調用方式

1. 靜態調用 (推薦)

FileUtil::createDir('storage/logs/2024/01');
FileUtil::copyFile('src/config.php', 'dist/config.php', true); // 覆蓋模式
FileUtil::moveDir('old_module', 'new_module');

2. 實例調用 (支持依賴注入容器)

$fu = new FileUtil();
$fu->copyFile('a/1/2/3', 'a/1/2/4');

核心設計亮點

特性實現方式收益
路徑跨平台兼容normalize() 統一分隔符Windows/Linux 無縫運行
遞歸目錄處理RecursiveIteratorIterator CHILD_FIRST/SELF_FIRST正確處理巢狀結構,避免「目錄非空無法刪除」
覆蓋控制$overWrite 參數統一所有方法明確語義,避免靜默覆蓋數據丟失
錯誤抑制與返回值@unlink/@rmdir + bool 返回調用者自主決定錯誤處理策略
移動跨文件系統安全copyDir + unlinkDir 組合rename() 跨分區失敗時自動降級

使用場景建議

  • 框架無文件系統抽象層時的基礎設施代碼
  • 安裝腳本、部署腳本、緩存清理任務
  • 用戶上傳文件整理、臨時文件管理
  • 日誌輪轉、備份歸檔自動化腳本

擴展方向

  1. 集成 League\Flysystem 適配器,支持 S3、FTP、SFTP、Zip 等存儲後端。
  2. 添加文件鎖機制 (flock) 保證并發寫入安全。
  3. 實現 Psr\SimpleCache\CacheInterface 將文件系統作為緩存驅動。
  4. 添加 getSize()、getMimeType()、find() 等查詢方法。

總結

FileUtil 以 靜態方法、統一路徑處理、遞歸迭代器、覆蓋控制 四大特性,將零散的原生函數整合為連貫、可測試、生產可用的工具類。直接複製到項目 Common/Util/ 目錄即可使用,零依賴、零配置。

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