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

PHP 讀取檔案三種方式完整比較:fopen、file_get_contents、逐行讀取

     編輯:PHP 相關知識

前言

PHP 提供多種讀取檔案的方式,各有適用場景與效能特性。本文詳細比較 fopen/fread、file_get_contents、fopen/feof/fread 迴圈 三種核心方法,並補充 SplFileObject、parse_ini_file 等現代替代方案。

方法一:fopen + fread(傳統流式讀取)

<?php
$file = 'text.txt';
$encoding = 'UTF-8';

if (!file_exists($file)) {
    die("檔案不存在: $file");
}

$handle = fopen($file, 'r'); // 'r' 唯讀,指標在開頭
if (!$handle) {
    die("無法開啟檔案: $file");
}

// 一次讀取全部內容
$content = fread($handle, filesize($file));
fclose($handle);

// 處理換行符顯示(Web 環境)
$content = str_replace(["\r\n", "\r", "\n"], '<br>', $content);
echo $content;
?>

特點

  • 可控制讀取位元組數、指標位置(fseek)。
  • 需手動 fclose,否則洩露檔案描述符。
  • 適合二進位檔案、大檔案分塊讀取。

方法二:file_get_contents(一行式全讀,PHP 4.3+)

<?php
$file = 'text.txt';
$content = @file_get_contents($file); // @ 抑制警告

if ($content === false) {
    die("讀取失敗或檔案不存在");
}

// 直接輸出(已含換行符)
echo nl2br($content); // nl2br 自動將 \n \r\n 轉 
?>

特點

  • 程式碼最簡潔,內部使用記憶體映射 (mmap) 效能極佳。
  • 一次載入整個檔案到記憶體,大檔案(> 可用記憶體)會導致 OOM。
  • 支援 URL 封裝協議(https://, ftp://),需開啟 allow_url_fopen。

方法三:逐行讀取(大檔案、記憶體友善)

<?php
$file = 'large.log';
$handle = fopen($file, 'r');
if (!$handle) die("無法開啟");

$buffer = 8192; // 8KB 緩衝區
$line_number = 0;

while (!feof($handle)) {
    $line = fgets($handle, $buffer); // 讀取一行(含換行符)
    if ($line === false) break;

    $line_number++;
    // 處理單行:解析、過濾、寫入資料庫...
    // 範例:過濾 ERROR 行
    if (strpos($line, 'ERROR') !== false) {
        echo "[$line_number] $line<br>";
    }
}
fclose($handle);
?>

進階:SplFileObject(物件導向、可迭代、PHP 5.1+)

<?php
$file = new SplFileObject('large.log', 'r');
$file->setFlags(
    SplFileObject::READ_AHEAD |   // 預讀
    SplFileObject::SKIP_EMPTY |   // 跳過空行
    SplFileObject::DROP_NEW_LINE  // 移除行尾換行符
);

foreach ($file as $line_num => $line) {
    if (strpos($line, 'ERROR') !== false) {
        echo "[$line_num] $line<br>";
    }
}
// 自動關閉,無需 fclose
?>

效能與記憶體對比(100MB 文字檔測試環境)

方法峰值記憶體耗時適用場景
file_get_contents~100 MB最快小檔案 (< 10MB)、配置檔、模板
fread(filesize)~100 MB快需二進位控制、指標操作
fgets 迴圈~8 KB (緩衝區)中等大檔案、日誌分析、逐行處理
SplFileObject~8 KB中等現代 OOP 代碼、可直接 foreach

特殊格式檔案讀取

INI 設定檔:parse_ini_file

<?php
// config.ini
; [database]
; host = localhost
; user = root
; pass = secret

$config = parse_ini_file('config.ini', true); // true = 保留 section
echo $config['database']['host']; // localhost
?>

CSV 檔案:fgetcsv

<?php
$handle = fopen('data.csv', 'r');
while (($row = fgetcsv($handle, 1000, ',')) !== false) {
    // $row 為欄位陣列
    print_r($row);
}
fclose($handle);
?>

JSON 檔案:json_decode + file_get_contents

<?php
$data = json_decode(file_get_contents('config.json'), true); // true = 關聯陣列
?>

常見錯誤與最佳實踐

  1. 編碼處理:讀取後立即 mb_convert_encoding($content, 'UTF-8', 'auto') 或指定來源編碼。
  2. 路徑安全:用戶輸入路徑需經 realpath() 解析並確認在允許目錄下,防止目錄遍歷。
  3. 錯誤處理:優先用 try/catch (SplFileObject 拋出 RuntimeException) 或檢查回傳值 === false。
  4. 大檔案務必逐行/分塊,嚴禁 file()、file_get_contents() 載入超過 memory_limit 的檔案。
  5. 獨佔鎖定:寫入前用 flock($handle, LOCK_EX),讀取可用 LOCK_SH 共享鎖。

總結

選擇讀取方式的決策樹:

  • 檔案 < 10MB 且需完整內容 → file_get_contents() 最簡潔。
  • 需二進位控制、指標操作 → fopen/fread/fseek。
  • 大檔案、日誌、逐行處理 → fgets() 迴圈或 SplFileObject。
  • 結構化格式 (INI, CSV, JSON) → 使用專用解析函數 (parse_ini_file, fgetcsv, json_decode)。

掌握三種核心方法特性,並善用現代 SplFileObject 簡化代碼,即能應對所有檔案讀取場景。

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