對於數 GB 的日誌檔,file() 讀入陣列會耗盡記憶體。利用檔案指標 fseek() 從檔案末尾反向搜尋換行符,僅讀取所需行數,記憶體佔用極低、速度極快。
fopen($file, 'r') 開啟檔案,指標初始在開頭。fseek($fp, -2, SEEK_END) 將指標移至倒數第二個位元組(避開 EOF)。fgetc($fp) 逐字元向前讀取,直到遇到 \n 判定為一行結尾。fgets($fp) 從該位置讀取完整一行。$n,內層迴圈控制指標後退。/**
* 取得檔案最後 $n 行
* @param string $filename 檔案路徑
* @param int $n 行數
* @return string|false 成功回傳字串,失敗回傳 false
*/
function FileLastLines($filename, $n) {
if (!$fp = fopen($filename, 'r')) {
echo "開啟檔案失敗,請檢查路徑是否正確(避免中文路徑)";
return false;
}
$pos = -2;
$eof = "";
$str = "";
while ($n > 0) {
while ($eof !== "\n") {
if (!fseek($fp, $pos, SEEK_END)) {
$eof = fgetc($fp);
$pos--;
} else {
break; // 已達檔案開頭
}
}
$str .= fgets($fp);
$eof = "";
$n--;
}
fclose($fp);
return $str;
}
// 使用範例
echo nl2br(FileLastLines('sss.txt', 4));
| 檔案大小 | file() 讀全檔 | FileLastLines() |
|---|---|---|
| 100 MB | 記憶體錯誤 / >5 秒 | < 0.01 秒,記憶體 < 1 MB |
| 1 GB | 不可行 | < 0.02 秒 |
SplFileObject 的 seek() 方法,語法更物件導向。指標法是 PHP 處理大檔案尾部資料的標準解法,核心只需 fseek、fgetc、fgets 三個函式,幾十行代碼即可替代昂貴的記憶體消耗。