統計大型文字檔 (如日誌、CSV、SQL dump) 行數是常見需求。本文對比兩種方法:stream_get_line() 逐行流式讀取 (常數記憶體) 與 count(file()) 一次性載入陣列 (記憶體隨檔案大小線性增長),分析效能差異、適用場景與邊界條件。
關鍵優勢:
"\n"、"\r\n"、"\r"、甚至自定義分隔符。運作機制:file() 將整個檔案讀入記憶體,按行分割為陣列返回。count() 計算陣列元素數。
缺點:
memory_limit (預設 128M) 會報錯中止。| 指標 | stream_get_line | count(file()) |
|---|---|---|
| 峰值記憶體 | ~2 MB | ~150 MB |
| 執行時間 | ~0.8 秒 | ~1.2 秒 |
| 穩定性 | ✅ 極佳 | ❌ 易 OOM |
exec("wc -l $file"):Linux/macOS 最快,調用系統工具,需注意命令注入風險 (escapeshellarg) 與跨平台相容性。fgets() 迴圈:while(fgets($fp)) $line++; 效能略遜於 stream_get_line (需掃描換行符)。$f = new SplFileObject($file); $f->seek(PHP_INT_MAX); echo $f->key() + 1; 物件導風格,內部同樣流式讀取。pcntl_fork 分塊並行計數再合併。檔案大小 < 10MB 且 memory_limit 充足 → count(file()) 最簡潔 檔案 10MB ~ 500MB → stream_get_line() / SplFileObject 檔案 > 500MB 或嵌入式環境 → stream_get_line() (調大緩衝區) 或 wc -l 跨平台 CLI 工具 → 封裝 stream_get_line 為預設,Linux 可選 wc -l 優化
掌握流式讀取技巧,不僅解決行數統計,更是處理大型 CSV 匯入、日誌分析、資料清洗等串流處理任務的核心基礎。