PHP 通過 `file()` 函數可一次性將文本文件讀入數組(每行一個元素),再配合循環遍歷輸出,是處理配置文件、日誌分析、數據導入的常用模式。本文詳細講解 `file()` 函數特性、逐行處理流程、內存考量及現代替代方案。
array file ( string $filename [, int $flags = 0 [, resource $context ]] )
<?php
$filename = 'data.txt';
// 文件內容:
// 第一行
// 第二行
// 第三行
// 1. 讀取文件到數組(自動去換行、跳空行)
$lines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($lines === false) {
die("無法讀取文件: $filename");
}
// 2. 遍歷輸出
foreach ($lines as $lineNum => $line) {
echo "第 " . ($lineNum + 1) . " 行: " . htmlspecialchars($line) . "
\n";
}
/* 輸出:
第 1 行: 第一行
第 2 行: 第二行
第 3 行: 第三行
*/
?>
<?php
// 解析簡單鍵值對配置:key=value
$config = [];
$lines = file('config.ini', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
$line = trim($line);
if ($line === '' || $line[0] === '#') continue; // 跳過註釋
if (($pos = strpos($line, '=')) !== false) {
$key = trim(substr($line, 0, $pos));
$value = trim(substr($line, $pos + 1));
$config[$key] = $value;
}
}
print_r($config);
/* 輸出示例:
Array
(
[db_host] => localhost
[db_port] => 3306
[debug] => true
)
*/
?>
| 特性 | file() | SplFileObject |
|---|---|---|
| 內存佔用 | O(文件大小) - 全量載入數組 | O(1) - 流式逐行迭代 |
| 適用文件大小 | < 100MB(視可用內存) | 無限制(GB 級) |
| 隨機訪問 | 支持($lines[100]) | 不支持(僅順序) |
| 性能 | 單次讀取快 | 逐行迭代略慢 |
| 功能豐富度 | 基礎 | 內置 CSV 解析、seek、current、key 等 |
<?php
$file = new SplFileObject('huge.log', 'r');
$file->setFlags(
SplFileObject::READ_CSV | // 自動解析 CSV(可選)
SplFileObject::DROP_NEW_LINE | // 去除換行
SplFileObject::SKIP_EMPTY // 跳過空行
);
// 若非 CSV,僅用 DROP_NEW_LINE | SKIP_EMPTY
foreach ($file as $lineNum => $line) {
// $line 可能是字符串(非 CSV 模式)或數組(CSV 模式)
if (is_array($line)) {
// CSV: [$col1, $col2, ...]
processCsvRow($line);
} else {
// 純文本行
processTextLine($line);
}
// 進度顯示
if ($lineNum % 10000 === 0) {
echo "已處理 $lineNum 行...\n";
}
}
// 文件句柄自動關閉,內存常數級
?>
<?php
function readLinesSafe($filename, $flags = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
{
if (!is_readable($filename)) {
throw new RuntimeException("文件不可讀: $filename");
}
$lines = @file($filename, $flags); // 抑制 warning,自行拋異常
if ($lines === false) {
throw new RuntimeException("文件讀取失敗: $filename");
}
return $lines;
}
try {
$data = readLinesSafe('data.txt');
// 處理...
} catch (RuntimeException $e) {
error_log($e->getMessage());
// 用戶友好提示或重試邏輯
}
?>
若文件為 GBK/GB2312 編碼,需轉碼後再處理:
$lines = file('gbk.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$lines = array_map(function($line) {
return iconv('GBK', 'UTF-8//IGNORE', $line);
}, $lines);
掌握 `file()` 與 `SplFileObject` 兩大工具的適用邊界,能讓你從容應對從配置文件到 TB 級日誌的各類文本處理需求。