应避免用file_get_contents处理大文件,因其全量加载必致内存溢出;推荐fopen+fgets流式逐行替换,内存恒定、逻辑清晰,但需显式指定长度参数防截断,注意换行符和编码问题。

别用 file_get_contents 替换大文件,它会直接把整个文件塞进内存,100MB 文件就吃掉 100MB 内存,超限立刻报 Fatal error: Allowed memory size exhausted——这不是你代码写错了,是函数设计如此。
fgets 逐行替换为什么最常用
适合按行匹配的场景(比如日志里改域名、批量修路径),内存恒定、逻辑清晰、兼容性好。
-
fgets($handle, 8192)必须显式传长度参数,否则默认只读 1024 字节,长行会被截断 - 返回的
$line带末尾\n,str_replace后别额外加换行,否则空行变多 - 原文件不是 UTF-8 编码时,
str_replace可能错位,先用mb_convert_encoding转码 - 二进制文件(PDF、图片等)不能用此法,
fgets会破坏字节流
跨行内容或正则替换怎么办
当要替换的是 HTML 标签、JSON 片段这类可能横跨多行的内容,或必须用 preg_replace,就得自己控制读取窗口。
- 用
fseek回退位置,每次读块前预留前一块末尾若干字节(建议预留长度 ≥ 关键词最大长度) - 读取块大小建议设为 64KB 左右,太小效率低,太大仍可能溢出
-
preg_replace后直接fwrite到新文件,不要尝试原地修改原文件 - 循环中记得调用
fflush($out),否则部分数据可能卡在缓冲区没写入磁盘
Linux 下该不该用 PHP 自己干
如果你在 Linux 环境且有 shell 权限,sed -i 或 perl -pi 几乎总是更快、更省内存,PHP 不是干这个的。
立即学习“PHP免费学习笔记(深入)”;
-
sed -i 's/http:\/\/old\.com/https:\/\/new\.com/g' /path/to/big.log一行搞定,不占 PHP 内存 - 注意
.、*、/等字符需转义,否则语法错误或误替换 - Perl 更擅长复杂正则,但依赖系统是否装了 Perl;
sed更通用 - 如果必须用 PHP(比如要集成到 Web 流程里),优先走流式处理,别硬扛
真正容易被忽略的是:哪怕用了 fgets,如果每行处理逻辑里悄悄 new 了对象、拼了大数组、或者忘了 unset 中间变量,内存还是会慢慢涨上去。流式只是起点,后续处理也得轻量。



















