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

PHP 檔案與目錄操作完全指南:8 大核心場景實戰解析

     編輯:PHP 綜合知識

前言

PHP 處理本地檔案系統功能強大,但常遇到權限、路徑、跨平台相容性問題。本文系統整理 8 大核心操作場景,提供最佳實務範例與避坑指南。

1. 開啟檔案:fopen() 完整參數解析

resource fopen ( string $filename, string $mode [, bool $use_include_path [, resource $context ]] )

模式對照表

模式讀/寫指標位置截斷建立適用場景
r唯讀開頭否否讀取現有檔案
r+讀寫開頭否否讀寫現有檔案
w唯寫開頭是是覆寫/新建檔案
w+讀寫開頭是是讀寫覆寫/新建
a唯寫結尾否是記錄檔、日誌追加
a+讀寫結尾否是追加並需讀取
x唯寫開頭否獨佔建立防止覆寫既有檔(PHP 4.3.2+)
x+讀寫開頭否獨佔建立同上,可讀寫

關鍵建議

  • 二進位檔案必須加 'b' 標記:'rb', 'wb' 避免 Windows \r\n 轉換損壞圖片/二進位資料
  • 路徑支援相對、絕對、URL 協議(https://, ftp:// 需 allow_url_fopen=On)
  • 錯誤處理:$fp = @fopen($file, 'rb') ?: throw new Exception("無法開啟: $file")

2. 關閉檔案:fclose() 釋放資源

bool fclose ( resource $handle )

確保緩衝區資料寫入磁碟、釋放檔案鎖定、歸還系統檔案描述符。良好習慣:配合 try/finally 或 register_shutdown_function 確保關閉。

3. 讀取檔案:多種方式對比

函式行為適用場景注意事項
fgets()讀一行(含換行符)文字檔逐行處理預設 1KB,可指定長度;二進位檔結果不可預期
fgetss()讀一行並移除 HTML 標籤解析含標籤文字可指定允許保留標籤
fgetc()讀單一字元字元級處理效能極差,避免大檔使用
fread()讀指定位元組二進位檔、大檔分塊讀取需指定長度,配合 filesize() 或循環讀取
file()整檔讀入陣列(每行一元素)小型設定檔、CSV大檔會耗盡記憶體
file_get_contents()整檔讀入字串小檔快速讀取、URL 內容同上,記憶體風險

大檔案分塊讀取標準模式

$handle = fopen('large.log', 'rb');
while (!feof($handle)) {
    $chunk = fread($handle, 8192); // 8KB 緩衝區
    process($chunk); // 處理邏輯
}
fclose($handle);

4. 檔案指標狀態判斷

  • feof($handle):到達 EOF 回傳 true
  • ftell($handle):取得當前指標位移(位元組)
  • fseek($handle, $offset, SEEK_SET|CUR|END):移動指標
  • rewind($handle):指標歸零
  • filesize($filename):取得檔案大小(快取結果,明確需 clearstatcache())

5. 寫入檔案:fwrite() 與檔案鎖定

int fwrite ( resource $handle, string $string [, int $length ] )

安全寫入範本(含獨佔鎖定)

$file = 'data.txt';
$content = "新資料\n";

$fp = fopen($file, 'c+'); // 開啟讀寫、不截斷、建立新檔
if (flock($fp, LOCK_EX)) { // 獨佔鎖定
    ftruncate($fp, 0); // 清空內容(如需覆寫)
    fwrite($fp, $content);
    fflush($fp); // 強制刷新到作業系統緩衝區
    flock($fp, LOCK_UN); // 釋放鎖定
} else {
    throw new Exception("無法取得檔案鎖定");
}
fclose($fp);

二進位資料寫入

$binary = file_get_contents('image.png');
$result = fwrite($fp, $binary, strlen($binary)); // PHP 5.6+ 可省略長度
// 或 mb_strlen($binary, '8bit') 確保位元組長度

6. 檔案權限與屬性檢查

函式回傳值說明
is_readable()bool可讀(含權限、存在性)
is_writable() / is_writeable()bool可寫
file_exists()bool存在(檔案/目錄/連結)
is_file()bool一般檔案
is_dir()bool目錄
fileperms()intUnix 權限位元組(配合 decoct() 顯示)
fileowner() / filegroup()int擁有者 UID/GID(需 POSIX 擴充)
filemtime() / fileatime() / filectime()int修改/存取/狀態改變時間戳

7. 刪除與重命名

bool unlink ( string $filename )      // 刪除檔案
bool rename ( string $old, string $new ) // 移動/重命名(跨檔案系統可能失敗)

注意: 刪除前建議 is_writable() 檢查目錄權限;重命名可用於原子性更新(寫暫存檔 → rename 覆蓋目標)。

8. 目錄操作完整 API

路徑處理

basename($path)        // 檔案名
dirname($path)         // 目錄路徑
pathinfo($path)        // 關聯陣列:dirname, basename, extension, filename
realpath($path)        // 絕對路徑(解析連結、相對路徑)

目錄讀取

$dh = opendir('/path/to/dir');
while (($entry = readdir($dh)) !== false) {
    if ($entry === '.' || $entry === '..') continue;
    $full = '/path/to/dir/' . $entry;
    echo is_dir($full) ? "[DIR] $entry\n" : "[FILE] $entry\n";
}
closedir($dh);

// 現代寫法:DirectoryIterator (SPL)
foreach (new DirectoryIterator('/path') as $file) {
    if ($file->isDot()) continue;
    echo $file->getFilename() . ($file->isDir() ? '/' : '') . "\n";
}

目錄建立/刪除/切換

mkdir($path, 0755, true)  // 遞迴建立,權限受 umask 影響
rmdir($path)              // 僅限空目錄
chdir($path)              // 改變當前工作目錄(影響相對路徑)

實用工具函式:遞迴複製/刪除目錄

function rcopy($src, $dst) {
    $dir = opendir($src);
    @mkdir($dst, 0755, true);
    while (($file = readdir($dir)) !== false) {
        if ($file == '.' || $file == '..') continue;
        $srcPath = "$src/$file";
        $dstPath = "$dst/$file";
        if (is_dir($srcPath)) rcopy($srcPath, $dstPath);
        else copy($srcPath, $dstPath);
    }
    closedir($dir);
}

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

跨平台路徑最佳實務

  • 統一使用正斜線 /,PHP 在 Windows 也能正確解析
  • 使用 DIRECTORY_SEPARATOR 常數組合路徑
  • 避免硬編碼 C:\path,改用 __DIR__、getcwd()、環境變數
現代 PHP(7.1+)建議使用 SplFileObject 物件導向檔案操作,內建迭代器、CSV 解析、鎖定支援,程式碼更優雅、型別安全。大量檔案處理考慮非同步 I/O(Swoole、ReactPHP)或外部工具。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved