1. 開啟檔案
$fp = fopen('data.txt', 'rb'); // 相對路徑
$fp = fopen('/var/www/data.txt', 'rb'); // 絕對路徑
$fp = fopen('https://example.com/file.txt', 'rb'); // URL (需 allow_url_fopen=On)
$fp = fopen('ftp://user:pass@ftp.example.com/file.txt', 'rb'); // FTP
// 二進制模式建議永遠加 'b' 旗標,跨平台相容
// 失敗返回 false,建議用 @ 抑制警告再自行判斷
if (!$fp = @fopen('data.txt', 'rb')) {
throw new RuntimeException('無法開啟檔案');
}
2. 關閉檔案(必須顯式釋放資源)
fclose($fp); // 確保緩衝區寫入磁碟
3. 讀取檔案
| 函數 | 用途 | 注意 |
fgets($fp, 4096) | 逐行讀取文字檔 | 含換行符,二進制檔不可用 |
fgetcsv($fp) | 解析 CSV 行 | 自動處理引號、逗號 |
fread($fp, 8192) | 讀取指定位元組(二進制安全) | 大檔案分塊讀取 |
file_get_contents('data.txt') | 一次讀全檔 | 記憶體允許時使用 |
file('data.txt') | 整檔讀成陣列(每行一元素) | 含換行符 |
大檔案分塊讀取範例
$fp = fopen('large.bin', 'rb');
while (!feof($fp)) {
$chunk = fread($fp, 8192);
// 處理 $chunk
}
fclose($fp);
4. 判斷檔案狀態
feof($fp) // 是否到達 EOF
filesize('data.txt') // 檔案大小 (bytes)
fstat($fp) // 詳細 stat 資訊 (inode, mtime, mode...)
5. 寫入檔案
$fp = fopen('log.txt', 'ab'); // 追加模式
fwrite($fp, "Log entry\n");
// 二進制資料需指定長度
fwrite($fp, $binaryData, strlen($binaryData));
fclose($fp);
// 便利函數
file_put_contents('log.txt', "Log entry\n", FILE_APPEND | LOCK_EX); // 原子追加
6. 檔案權限與屬性檢查
is_readable('data.txt') // 可讀
is_writable('data.txt') // 可寫
is_file('data.txt') // 是一般檔案
is_dir('data') // 是目錄
file_exists('data.txt') // 存在
fileperms('data.txt') // 權限位元組 (0644 等)
fileowner('data.txt') // 擁有者 UID
filegroup('data.txt') // 群組 GID
filemtime('data.txt') // 最後修改時間
filectime('data.txt') // 狀態改變時間
7. 刪除與重命名
unlink('old.txt'); // 刪除檔案
rename('old.txt', 'new.txt'); // 重命名/移動 (跨裝置需 copy+unlink)
8. 目錄操作
// 掃描目錄
$files = scandir('/var/www'); // 含 . 與 ..
$files = array_diff(scandir($dir), ['.', '..']);
// 遞迴遍歷 (SPL)
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS));
foreach ($it as $file) {
echo $file->getPathname() . PHP_EOL;
}
// 建立/刪除目錄
mkdir('path/to/dir', 0755, true); // 遞迴建立
rmdir('empty_dir'); // 僅空目錄
// 路徑處理
basename('/path/to/file.txt'); // file.txt
dirname('/path/to/file.txt'); // /path/to
pathinfo('/path/to/file.txt'); // ['dirname'=>..., 'basename'=>..., 'extension'=>'txt', 'filename'=>'file']
realpath('../relative/path'); // 絕對路徑 (需存在)
安全檢查清單
- 所有來自用戶的路徑參數,**必須經過**
realpath() 解析並確認在允許根目錄內(str_starts_with($real, $allowedRoot))。
- 上傳檔案:驗證 MIME、副檔名、大小、
move_uploaded_file() 移至非公開目錄、重新命名亂碼檔名。
- 包含檔案:
include $userInput **嚴禁**;白名單 in_array($page, $allowed, true)。
- 權限最小化:Web 目錄
755/644,上傳/快取/日誌目錄 770 擁有者 www-data,禁用執行位元。
- 錯誤不外洩:生產環境
display_errors=Off,避免路徑洩露。