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

PHP 讀取大文本文件並分頁顯示:基於字節偏移的高效分頁方案

     編輯:PHP 相關知識

場景與挑戰

直接 file_get_contents 讀取超大文本(如日誌、小說)會耗盡內存。本文採用「全量讀取 → 字節計算偏移 → 截取片段」的簡易分頁策略,適合中小型文件(< 50MB)。大文件建議使用 fseek + fread 直接定位讀取。

完整實現代碼

<?php
session_start();
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
?>
<!DOCTYPE html>
<html><head>
<meta charset="UTF-8">
<title>文本分頁閱讀</title>
<style>
body {font-family: sans-serif; margin: 20px;}
.table {width: 100%; border-collapse: collapse; background: #f5f5f5;}
.content {white-space: pre-wrap; word-break: break-all; padding: 15px;}
.pager {text-align: center; margin-top: 10px;}
.pager a {margin: 0 5px; padding: 5px 10px; background: #eee; text-decoration: none; border-radius: 3px;}
.pager a:hover {background: #ddd;}
</style>
</head><body>

<div class="table">
<div class="content">
<?php
$file = 'example.txt';
if (!file_exists($file)) die('文件不存在');

$content = file_get_contents($file);
$totalBytes = strlen($content);
$pageSize = 5000; // 每頁字節數
$pageCount = ceil($totalBytes / $pageSize);
$page = min($page, $pageCount);

// 處理中文換行與雙字節字符的輔助函數
function msubstr($str, $start, $len) {
    $end = $start + $len;
    $tmp = '';
    for ($i = $start; $i < $end && $i < strlen($str); $i++) {
        $c = $str[$i];
        if ($c === "\n") { $tmp .= '<br />'; continue; }
        if (ord($c) > 0xA0) { // 簡易判斷雙字節
            $tmp .= $str[$i] . $str[$i+1];
            $i++;
        } else {
            $tmp .= $c;
        }
    }
    return $tmp;
}

$offsetStart = ($page - 1) * $pageSize;
$offsetEnd   = $page * $pageSize;

$prevPart = msubstr($content, 0, $offsetStart);
$currPart = msubstr($content, 0, $offsetEnd);
echo substr($currPart, strlen($prevPart));
?>
</div>
</div>

<div class="pager">
<span>第 <?php echo $page; ?> / <?php echo $pageCount; ?> 頁</span>
<?php
echo '<a href="?page=1">首頁</a> ';
if ($page > 1) echo '<a href="?page='.($page-1).'">上一頁</a> ';
if ($page < $pageCount) echo '<a href="?page='.($page+1).'">下一頁</a> ';
echo '<a href="?page='.$pageCount.'">尾頁</a>';
?>
</div>
</body></html>

關鍵技術點

  1. 字節級分頁:按固定字節數(5000)切分,避免按行讀取的複雜度。
  2. 中文兼容:msubstr 通過 ord() > 0xA0 簡易識別雙字節字符(GBK/UTF-8 均可粗略處理),保證不截斷半個漢字。
  3. 換行轉換:將 \n 轉為 <br /> 保持頁面換行顯示。
  4. 偏移計算:利用 substr($currPart, strlen($prevPart)) 精確提取當前頁內容。

局限與改進

  • 內存佔用:全量讀取文件,大文件會 OOM。改進:使用 fopen + fseek 直接跳轉到偏移位置讀取固定長度。
  • 編碼假設:簡易雙字節判斷在 UTF-8 下可能誤判(UTF-8 中文高位不一定 > 0xA0)。改進:配合 mb_substr 或預先轉碼。
  • 性能:每次請求都全量讀取並雙重 msubstr。改進:緩存文件內容或分頁索引。

生產級建議

對於大文件分頁,推薦:

  1. 預處理建立行號/字節偏移索引文件(或 SQLite 表)。
  2. 請求時查詢索引定位 fseek 讀取。
  3. 前端配合虛擬滾動或無限加載提升體驗。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved