在資料處理任務中,逐行讀取文字檔並轉換為陣列結構是極為常見的需求。無論是處理用戶名單、日誌分析、設定檔解析,或是批次匯入資料,掌握高效且記憶體友善的讀取技巧至關重要。本文將詳細解析 PHP 逐行讀取 TXT 檔案的核心方法,並提供優化建議。
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);
false,建議搭配錯誤處理$length - 1 個位元組feof() 在讀取最後一行後才會回傳 true,因此迴圈結構 while(!feof()) 是標準寫法""、0、null、false 等)fgets() 讀取檔案末尾可能產生的空字串問題array_values()$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);
針對超大檔案(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);
}
| 方法 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
file() | 一行程式碼讀整檔成陣列 | 大檔案記憶體壓力大 | 小檔案、快速原型 |
file_get_contents() + explode() | 靈活控制分隔符 | 同樣載入整檔到記憶體 | 需自定分隔符的小檔案 |
SplFileObject | 物件導向、可迭代、支援 CSV 解析 | 較底層函數略慢 | 現代化專案、結構化資料 |
fopen/fgets (本文方法) | 記憶體效率最高、流式處理 | 程式碼較冗長 | 大檔案、長時間運行腳本 |
iconv() 或 mb_convert_encoding() 轉為 UTF-8\r\n、Linux \n、Mac \r,建議統一用 rtrim($line, "\r\n") 處理\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() 清理空值、生成器模式應對超大檔案、完善的錯誤處理與編碼轉換,即可構建健壯的檔案解析功能。開發者應根據檔案大小、記憶體限制與業務複雜度,選擇最適合的讀取策略。