file() 一次性載入記憶體,大檔案直接 OOM。fgets() 逐行讀取,IO 系統呼叫過多,極慢。/**
* 高效率計算檔案行數
* @param string $file 檔案路徑
* @return int 行數
*/
function count_line(string $file): int {
$fp = fopen($file, 'r');
if (!$fp) return 0;
$count = 0;
$chunkSize = 1024 * 1024 * 2; // 2MB 每塊
while (!feof($fp)) {
$data = fread($fp, $chunkSize);
if ($data === false) break;
$count += substr_count($data, "\n");
}
fclose($fp);
return $count;
}
| 執行次數 | 行數 | 耗時 |
|---|---|---|
| 1 | 13,214,810 | 56.28 秒 |
| 2 | 13,214,810 | 49.67 秒 |
對比:fgets() 逐行讀取同檔案需 20+ 分鐘。
\r\n 會被計為兩行,實際行數需 substr_count($data, "\n");若需精確可先 str_replace("\r\n", "\n", $data)。\n,結果會少 1。可補檢 !feof($fp) && $data !== '' 邏輯。0x0A,UTF-8/GBK/二進位皆適用。// Swoole 任務異步統計
Swoole\Async::readFile($file, function($filename, $content) {
$lines = substr_count($content, "\n");
// 回寫快取或資料庫
});
分塊讀取 + substr_count 是 PHP 單程序統計大檔案行數的最優解,簡單、記憶體常數級、速度接近磁碟順序讀取上限。