PHP 提供多種讀取檔案的方式,各有適用場景與效能特性。本文詳細比較 fopen/fread、file_get_contents、fopen/feof/fread 迴圈 三種核心方法,並補充 SplFileObject、parse_ini_file 等現代替代方案。
<?php
$file = 'text.txt';
$encoding = 'UTF-8';
if (!file_exists($file)) {
die("檔案不存在: $file");
}
$handle = fopen($file, 'r'); // 'r' 唯讀,指標在開頭
if (!$handle) {
die("無法開啟檔案: $file");
}
// 一次讀取全部內容
$content = fread($handle, filesize($file));
fclose($handle);
// 處理換行符顯示(Web 環境)
$content = str_replace(["\r\n", "\r", "\n"], '<br>', $content);
echo $content;
?>
fseek)。fclose,否則洩露檔案描述符。<?php
$file = 'text.txt';
$content = @file_get_contents($file); // @ 抑制警告
if ($content === false) {
die("讀取失敗或檔案不存在");
}
// 直接輸出(已含換行符)
echo nl2br($content); // nl2br 自動將 \n \r\n 轉
?>
https://, ftp://),需開啟 allow_url_fopen。<?php
$file = 'large.log';
$handle = fopen($file, 'r');
if (!$handle) die("無法開啟");
$buffer = 8192; // 8KB 緩衝區
$line_number = 0;
while (!feof($handle)) {
$line = fgets($handle, $buffer); // 讀取一行(含換行符)
if ($line === false) break;
$line_number++;
// 處理單行:解析、過濾、寫入資料庫...
// 範例:過濾 ERROR 行
if (strpos($line, 'ERROR') !== false) {
echo "[$line_number] $line<br>";
}
}
fclose($handle);
?>
<?php
$file = new SplFileObject('large.log', 'r');
$file->setFlags(
SplFileObject::READ_AHEAD | // 預讀
SplFileObject::SKIP_EMPTY | // 跳過空行
SplFileObject::DROP_NEW_LINE // 移除行尾換行符
);
foreach ($file as $line_num => $line) {
if (strpos($line, 'ERROR') !== false) {
echo "[$line_num] $line<br>";
}
}
// 自動關閉,無需 fclose
?>
| 方法 | 峰值記憶體 | 耗時 | 適用場景 |
|---|---|---|---|
file_get_contents | ~100 MB | 最快 | 小檔案 (< 10MB)、配置檔、模板 |
fread(filesize) | ~100 MB | 快 | 需二進位控制、指標操作 |
fgets 迴圈 | ~8 KB (緩衝區) | 中等 | 大檔案、日誌分析、逐行處理 |
SplFileObject | ~8 KB | 中等 | 現代 OOP 代碼、可直接 foreach |
<?php
// config.ini
; [database]
; host = localhost
; user = root
; pass = secret
$config = parse_ini_file('config.ini', true); // true = 保留 section
echo $config['database']['host']; // localhost
?>
<?php
$handle = fopen('data.csv', 'r');
while (($row = fgetcsv($handle, 1000, ',')) !== false) {
// $row 為欄位陣列
print_r($row);
}
fclose($handle);
?>
<?php
$data = json_decode(file_get_contents('config.json'), true); // true = 關聯陣列
?>
mb_convert_encoding($content, 'UTF-8', 'auto') 或指定來源編碼。realpath() 解析並確認在允許目錄下,防止目錄遍歷。try/catch (SplFileObject 拋出 RuntimeException) 或檢查回傳值 === false。file()、file_get_contents() 載入超過 memory_limit 的檔案。flock($handle, LOCK_EX),讀取可用 LOCK_SH 共享鎖。選擇讀取方式的決策樹:
file_get_contents() 最簡潔。fopen/fread/fseek。fgets() 迴圈或 SplFileObject。parse_ini_file, fgetcsv, json_decode)。掌握三種核心方法特性,並善用現代 SplFileObject 簡化代碼,即能應對所有檔案讀取場景。