文件系統操作是 PHP 開發核心技能之一。本文系統總結目錄遍歷、文件讀寫、屬性獲取、權限控制等關鍵知識點,並提供最佳實踐代碼模式。
<?php
$baseDir = __DIR__ . '/filelist';
$handle = opendir($baseDir);
if ($handle === false) {
die('無法打開目錄');
}
echo "目錄: $baseDir
";
while (($file = readdir($handle)) !== false) {
echo htmlspecialchars($file) . "
";
}
closedir($handle);
?>
<?php
$d = dir('/etc/php5');
echo "Handle: {$d->handle}
";
echo "Path: {$d->path}
";
while (($entry = $d->read()) !== false) {
echo htmlspecialchars($entry) . "
";
}
$d->close();
?>
<?php
$path = './data/logs/2024/01';
// 遞歸創建,權限 0755(受 umask 影響)
if (!is_dir($path)) {
mkdir($path, 0755, true); // true 遞歸創建
}
// 刪除空目錄
rmdir('./tmp/empty_dir');
// 非空目錄需遞歸刪除
function rrmdir($dir) {
foreach (glob($dir . '/*') as $file) {
is_dir($file) ? rrmdir($file) : unlink($file);
}
rmdir($dir);
}
?>
dirname($path):返回目錄部分basename($path):返回文件名部分disk_free_space($path):剩余磁盤空間(字節)realpath($path):獲取絕對路徑(解析轉義符)<?php
$file = 'dirlist.php';
// 是否存在
if (!file_exists($file)) die('文件不存在');
// 是否可讀
if (!is_readable($file)) die('無讀取權限');
// 是否可寫
if (!is_writable($file)) die('無寫入權限');
// 詳細屬性
echo "大小: " . filesize($file) . " 字節
";
echo "修改時間: " . date('Y-m-d H:i:s', filemtime($file)) . "
";
echo "訪問時間: " . date('Y-m-d H:i:s', fileatime($file)) . "
";
echo "類型: " . filetype($file) . "
"; // file, dir, link 等
echo "擁有者: " . fileowner($file) . "
";
echo "組: " . filegroup($file) . "
";
echo "權限: " . substr(sprintf('%o', fileperms($file)), -4) . "
";
?>
| 方法 | 適用場景 | 性能/記憶體 |
|---|---|---|
| file_get_contents() | 小文件、簡單讀取 | 一次性載入內存 |
| fopen + fread + fclose | 大文件、二進制、需控制讀取長度 | 流式,內存可控 |
| file() | 按行讀取為數組 | 整文件載入內存 |
| SplFileObject | 面向對象、可迭代、支持 CSV 解析 | 流式,功能最豐富 |
<?php
$handle = fopen('large.log', 'rb');
if ($handle) {
while (!feof($handle)) {
$chunk = fread($handle, 8192); // 8KB 塊
// 處理 $chunk
echo $chunk;
}
fclose($handle);
}
?>
<?php
$file = new SplFileObject('data.csv');
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY);
foreach ($file as $row) {
// $row 為數組
print_r($row);
}
?>
<?php
$content = "日誌內容\n";
file_put_contents('app.log', $content, FILE_APPEND | LOCK_EX); // 追加+獨佔鎖
?>
<?php
$handle = fopen('export.csv', 'wb');
if ($handle) {
fwrite($handle, "ID,Name,Email\n");
foreach ($users as $user) {
fputcsv($handle, [$user['id'], $user['name'], $user['email']]);
}
fclose($handle);
}
?>
<?php
$tmpFile = 'config.php.tmp';
$target = 'config.php';
file_put_contents($tmpFile, $newContent);
rename($tmpFile, $target); // 原子操作(同文件系統下)
?>
<?php
$fp = fopen('counter.txt', 'c+'); // 打開/創建,指針在開頭
if (flock($fp, LOCK_EX)) { // 獨佔鎖
$count = (int)fread($fp, filesize('counter.txt'));
$count++;
ftruncate($fp, 0); // 清空
rewind($fp);
fwrite($fp, (string)$count);
fflush($fp);
flock($fp, LOCK_UN); // 釋放
}
fclose($fp);
?>
掌握這些模式,能讓你在處理上傳、日誌、緩存、導出等文件密集型任務時游刃有余。