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

PHP 逐行讀取 TXT 檔案並寫入陣列的高效實作方法

     編輯:PHP 綜合知識

前言

在資料處理任務中,逐行讀取文字檔並轉換為陣列結構是極為常見的需求。無論是處理用戶名單、日誌分析、設定檔解析,或是批次匯入資料,掌握高效且記憶體友善的讀取技巧至關重要。本文將詳細解析 PHP 逐行讀取 TXT 檔案的核心方法,並提供優化建議。

核心實作:fopen + fgets + feof 黃金組合

PHP 提供了底層檔案操作函數組合,可實現流式讀取,避免一次性載入大檔案導致記憶體耗盡:

$file = fopen("username.txt", "r");
$user = array();
$i = 0;

// 輸出文本中所有的行,直到文件結束為止
while (!feof($file)) {
    $user[$i] = fgets($file); // fgets() 從檔案指標讀取一行
    $i++;
}

fclose($file);
$user = array_filter($user); // 移除空值元素
print_r($user);

關鍵函數深度解析

fopen($filename, $mode)

  • 模式 "r":唯讀模式,指標指向檔案開頭,檔案必須存在
  • 回傳檔案指標資源,後續操作均依賴此資源
  • 失敗時回傳 false,建議搭配錯誤處理

fgets($handle, $length = 1024)

  • 從檔案指標讀取一行(含換行符),最多讀取 $length - 1 個位元組
  • 遇到換行符、EOF 或讀取滿指定長度時停止
  • 適合逐行處理,記憶體佔用極低

feof($handle)

  • 檢查檔案指標是否到達 EOF(End Of File)
  • 注意:feof() 在讀取最後一行後才會回傳 true,因此迴圈結構 while(!feof()) 是標準寫法

array_filter($array)

  • 移除陣列中的空值元素(""、0、null、false 等)
  • 解決 fgets() 讀取檔案末尾可能產生的空字串問題
  • 保留鍵值關聯,若需重新索引可搭配 array_values()

進階優化與最佳實踐

1. 錯誤處理與資源保護

$file = @fopen("username.txt", "r");
if (!$file) {
    throw new Exception("無法開啟檔案:username.txt");
}

try {
    $user = array();
    while (!feof($file)) {
        $line = fgets($file);
        if ($line !== false) {
            $user[] = rtrim($line, "\r\n"); // 移除換行符
        }
    }
} finally {
    fclose($file); // 確保檔案關閉
}

$user = array_filter($user);

2. 大檔案處理:生成器模式

針對超大檔案(GB 級),建議使用生成器避免記憶體爆炸:

function readLines($filename) {
    $file = fopen($filename, "r");
    try {
        while (!feof($file)) {
            $line = fgets($file);
            if ($line !== false) {
                yield rtrim($line, "\r\n");
            }
        }
    } finally {
        fclose($file);
    }
}

// 使用方式:逐行處理,不載入整個陣列
foreach (readLines("huge_file.txt") as $line) {
    // 處理單行資料
    processLine($line);
}

3. 替代方案比較

方法優點缺點適用場景
file()一行程式碼讀整檔成陣列大檔案記憶體壓力大小檔案、快速原型
file_get_contents() + explode()靈活控制分隔符同樣載入整檔到記憶體需自定分隔符的小檔案
SplFileObject物件導向、可迭代、支援 CSV 解析較底層函數略慢現代化專案、結構化資料
fopen/fgets (本文方法)記憶體效率最高、流式處理程式碼較冗長大檔案、長時間運行腳本

4. 編碼與換行符處理

  • 編碼轉換:若檔案為 Big5/GBK 編碼,讀取後需 iconv() 或 mb_convert_encoding() 轉為 UTF-8
  • 跨平台換行符:Windows \r\n、Linux \n、Mac \r,建議統一用 rtrim($line, "\r\n") 處理
  • BOM 處理:UTF-8 with BOM 檔案首行會有 \xEF\xBB\xBF,可用 substr() 移除

實戰範例:處理用戶名單匯入

function importUsers($filename) {
    $file = fopen($filename, "r");
    if (!$file) return ["success" => 0, "failed" => 0, "errors" => []];

    $users = [];
    $lineNum = 0;
    $errors = [];

    while (!feof($file)) {
        $lineNum++;
        $line = fgets($file);
        if ($line === false) continue;
        
        $username = trim($line);
        if (empty($username)) continue; // 跳過空行
        
        // 業務驗證:長度、格式、重複檢查等
        if (strlen($username) < 3 || strlen($username) > 20) {
            $errors[] = "第 $lineNum 行:用戶名長度不合法 ($username)";
            continue;
        }
        if (in_array($username, $users)) {
            $errors[] = "第 $lineNum 行:重複用戶名 ($username)";
            continue;
        }
        
        $users[] = $username;
    }
    fclose($file);

    // 批次寫入資料庫...
    // $successCount = batchInsertUsers($users);

    return [
        "total_lines" => $lineNum,
        "valid_users" => count($users),
        "errors" => $errors
    ];
}

總結

fopen() + fgets() + feof() 組合是 PHP 逐行讀取大型文字檔的標準且最高效方案。配合 array_filter() 清理空值、生成器模式應對超大檔案、完善的錯誤處理與編碼轉換,即可構建健壯的檔案解析功能。開發者應根據檔案大小、記憶體限制與業務複雜度,選擇最適合的讀取策略。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved