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

PHP 讀取超大文件實戰:按行讀取、尾部讀取、內存安全方案

     編輯:PHP 綜合知識

大文件(GB 級)不可一次性 file_get_contents 載入內存,必須**流式讀取**。本文提供三類實用函數:fgets 逐行讀取、fseek+SEEK_END 讀取最後 N 行、分塊緩衝 高性能尾部讀取。

1. 逐行讀取(通用、內存恆定)

$fp = fopen('huge.log', 'r');
while (($line = fgets($fp)) !== false) {
    // 處理單行 $line
    // 內存佔用僅為單行大小
}
fclose($fp);

2. 讀取文件最後 N 行(核心:fseek 從末尾倒序)

/**
 * 返回文件最後 $n 行字符串
 */
function FileLastLines($filename, $n)
{
    if (!$fp = fopen($filename, 'r')) 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));

3. 高性能尾部讀取(分塊緩衝,適合超大文件)

function tail($fp, $n, $base = 5)
{
    assert($n > 0);
    $pos = $n + 1;
    $lines = [];
    while (count($lines) <= $n) {
        try {
            fseek($fp, -$pos, SEEK_END);
        } catch (Exception $e) {
            fseek($fp, 0);
            break;
        }
        $pos *= $base; // 指數增大讀取塊
        while (!feof($fp)) {
            array_unshift($lines, fgets($fp));
        }
    }
    return array_slice($lines, 0, $n);
}
// 使用
$lines = tail(fopen("access.log", "r"), 10);
var_dump($lines);

4. 簡潔版尾部讀取(單循環)

$fp = fopen($file, "r");
$line = 10; $pos = -2; $t = " "; $data = "";
while ($line > 0) {
    while ($t != "\n") {
        fseek($fp, $pos, SEEK_END);
        $t = fgetc($fp);
        $pos--;
    }
    $t = " ";
    $data .= fgets($fp);
    $line--;
}
fclose($fp);
echo $data;

選擇建議

場景推薦方法特點
逐行處理日誌/CSVfgets() 循環簡單、穩定、內存 O(1)
獲取最後 N 行(中小文件)FileLastLines()代碼少、易理解
獲取最後 N 行(超大文件、高頻)tail() 分塊緩衝減少 fseek 系統調用、性能最優

避坑提醒

  • Windows 換行符 \r\n 可能導致 $eof != "\n" 判斷失效,建議用 trim() 或檢測 PHP_EOL。
  • fseek($fp, -$offset, SEEK_END) 偏移量超過文件大小會報錯,需 try-catch 或檢查返回值。
  • 頻繁讀取大文件尾部建議引入 **inotify / tail -f / Logstash / Filebeat** 等專業日誌採集工具,而非 PHP 輪詢。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved