首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 大文件高效讀寫實戰:file_get_contents+explode、數組翻轉查找、序列化存儲性能對比

     編輯:PHP 相關知識

處理百萬行級文本文件(如日志、字典、導出數據)時,file() 逐行讀入數組極其低效。本文實測對比三大優化方向:讀取方式、查找算法、存儲格式,給出高性能最佳實踐組合。

一、文件讀取:拒絕 file(),擁抱 file_get_contents + explode

<?php
// ❌ 低效:file() 逐行分配數組元素,內存碎片化嚴重
$lines = file('huge.txt'); // 100萬行約 2.5 秒

// ✅ 高效:整體讀入字符串,單次 explode 切割
$content = file_get_contents('huge.txt'); // 0.3 秒
$lines = explode("\n", $content);         // 0.4 秒
// 總耗時約 0.7 秒,提速 3.5 倍

// 進階:超大文件分塊讀取(生成器模式)
function readLines(string $file): Generator {
    $fp = fopen($file, 'r');
    while (($line = fgets($fp)) !== false) {
        yield rtrim($line, "\r\n");
    }
    fclose($fp);
}
foreach (readLines('huge.txt') as $line) { /* 處理 */ } // 常數內存
?>

二、數組查找:翻轉數組實現 O(1) 存在性判斷

<?php
$lines = explode("\n", file_get_contents('dict.txt')); // 100萬詞

// ❌ 低效:in_array 線性掃描 O(n)
if (in_array('target', $lines)) { ... } // 平均 50萬次比較

// ✅ 高效:翻轉數組,鍵為值,值為 1,isset 判斷 O(1)
$dict = array_flip($lines); // 或 array_fill_keys($lines, 1)
if (isset($dict['target'])) { ... } // 1 次哈希查找

// 內存權衡:array_flip 後值全為 1,比原數組略省內存
// 適用場景:靜態字典、白名單、停用詞表、ID 集合
?>

三、數據存儲:序列化格式性能實測

將處理後的大數組持久化到文件,下次直接載入:

格式寫入代碼讀取代碼寫入耗時讀取耗時文件體積綜合評分
PHP 代碼 var_exportfile_put_contents('a.php', '$arr = include 'a.php';慢中大⭐⭐
serializefile_put_contents('a.dat', serialize($arr));$arr = unserialize(file_get_contents('a.dat'));最快最快中⭐⭐⭐⭐⭐
JSONfile_put_contents('a.json', json_encode($arr));$arr = json_decode(file_get_contents('a.json'), true);快快小⭐⭐⭐⭐
igbinary (擴展)file_put_contents('a.ig', igbinary_serialize($arr));$arr = igbinary_unserialize(file_get_contents('a.ig'));極快極快最小⭐⭐⭐⭐⭐+

實測結論:serialize 綜合性能最佳(PHP 原生、無解析開銷、支持所有類型)。跨語言交換用 JSON。極致性能安裝 igbinary 擴展。

四、綜合最佳實踐模板

<?php
// 1. 讀取大文件構建查找表
function buildDict(string $sourceFile, string $cacheFile): void {
    $content = file_get_contents($sourceFile);
    $lines = explode("\n", $content);
    $dict = array_flip($lines); // 或 array_fill_keys($lines, 1)
    file_put_contents($cacheFile, serialize($dict));
}

// 2. 業務使用:極速載入 + O(1) 查找
$dictFile = 'dict.cache';
if (!file_exists($dictFile) || filemtime($dictFile) < filemtime('dict.txt')) {
    buildDict('dict.txt', $dictFile);
}
$dict = unserialize(file_get_contents($dictFile));

// 3. 查找
function exists(string $word, array $dict): bool {
    return isset($dict[$word]);
}

// 4. 批量檢查(如敏感詞過濾)
function filterWords(string $text, array $dict): string {
    // 簡單演示:實際用 AC 自動機/Trie 樹
    foreach ($dict as $word => $_) {
        if (str_contains($text, $word)) {
            $text = str_replace($word, str_repeat('*', mb_strlen($word)), $text);
        }
    }
    return $text;
}
?>

五、避坑指南

  • 行尾符差異:Windows \r\n、Linux \n、Mac \r,用 preg_split('/\r\n|\r|\n/') 兼容
  • 內存峰值:file_get_contents 需要文件大小 2-3 倍內存,超大文件(>500MB)必須用生成器分塊處理
  • 序列化安全:unserialize 可能觸發對象注入,僅用於可信數據,或用 json/igbinary
  • OPcache 衝突:include 'a.php' 方式會被 OPcache 緩存,更新文件後需重啟或 opcache_invalidate()
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved