循环中反复 fopen 写文件变慢是因为每次调用都会清空文件、重建句柄,叠加磁盘 I/O 开销,且出错易致数据截断;应改用追加模式、批量写入或内存拼接后一次性落盘。

循环中反复 fopen 写文件为什么越来越慢?
因为每次 fopen(..., 'w') 都会清空文件并重建句柄,磁盘 I/O 开销叠加,尤其在大循环里明显卡顿。更糟的是,如果循环中途出错,文件可能被截断丢失前面写入的内容。
- 改用
fopen(..., 'a')追加模式,打开一次即可(但注意需手动控制换行或分隔符) - 高频小写入场景下,优先用
file_put_contents($path, $data, FILE_APPEND | LOCK_EX),它自动处理打开、写入、关闭和锁机制 - 若需格式化(如 CSV 行、JSON 数组追加),先在内存拼好整块字符串,再一次性写入,避免反复系统调用
foreach 里读 fgets 文件却只读第一行?
因为 fgets 是有状态的——它依赖文件指针位置。在循环外只调用一次 fopen,但没重置指针或重复调用 fgets,就会停在开头不动。
- 正确做法:把
fgets放进while (($line = fgets($fp)) !== false)循环里,而不是套在foreach外层 - 如果真要用
foreach遍历行,先用file($path)把文件全读进数组(适合小文件),再foreach ($lines as $line) - 大文件别用
file(),内存爆炸;也别在foreach里反复fopen + fgets + fclose,开销翻倍
循环变量名和 fwrite 写入内容对不上?
常见于变量作用域混淆:比如在 for 中用 $i 做索引,但写入时误用了同名的全局变量或闭包外的旧值;或者字符串拼接时忘了加点号 .,导致覆盖而非追加。
- 检查是否在循环内重新声明了同名变量,例如
$data = [];写在循环里,每次都会清空 -
fwrite($fp, $line . PHP_EOL)中的.容易漏,漏了就变成fwrite($fp, $line PHP_EOL)(语法错误)或隐式转换出错 - 调试时直接
var_dump($line)看实际值,别只信变量名——尤其从$_POST或数据库取的数据带空格、BOM、\0 字符时,肉眼难识别
用 glob 遍历文件再循环读写,遇到中文路径就失败?
PHP 的 glob 和默认文件函数不原生支持 UTF-8 路径(尤其 Windows),返回的文件名可能是乱码或直接跳过,导致循环根本没跑预期文件。
立即学习“PHP免费学习笔记(深入)”;
- Windows 下优先用
scandir()替代glob(),它对编码更宽容;再配合mb_convert_encoding()做一次转码(如mb_convert_encoding($filename, 'UTF-8', 'GBK')) - Linux/macOS 一般没问题,但若挂载了 NTFS 分区,仍可能因挂载参数(如
iocharset=utf8)缺失导致读取异常 - 最稳的方式:把待处理文件路径存在数据库或 JSON 列表里,用已知编码生成,绕过文件系统层面的编码猜测



















