file_get_contents和file_put_contents可覆盖80%日常需求;读小文件用前者,注意BOM和空字符串判断;写日志需FILE_APPEND与LOCK_EX;大文件须用fgets逐行处理,避免内存溢出。

直接用 file_get_contents 和 file_put_contents 就能覆盖 80% 的日常需求,不用手动 fopen/fclose,除非你要控制锁、分块读写或处理超大文件。
读小文件就用 file_get_contents,别碰 fread + fopen
它把整个文件当字符串一次性读进来,代码短、不易出错,适合配置、JSON、日志片段这类几 MB 以内的内容。
- 失败时返回
false,必须用=== false判断,不能只写if (!$content)(空字符串也会被误判) - 不自动处理换行符或 BOM,读 UTF-8 文件时如果开头有 BOM,
json_decode会直接失败 - 不支持跳过空行或忽略换行符——这些功能得换
file()函数并传FILE_SKIP_EMPTY_LINES - 路径里含用户输入时,务必先用
realpath()+is_file()校验,否则可能被../绕过导致读取敏感文件
写日志或追加内容,file_put_contents 必须带 FILE_APPEND
默认行为是覆盖,一不留神就把原有内容清空了。追加场景下漏掉 FILE_APPEND 是最常见错误。
- 单次写入就用
file_put_contents($path, $data, FILE_APPEND | LOCK_EX):加LOCK_EX防并发写乱,尤其在 Web 请求高频写日志时 -
FILE_APPEND不会自动加换行符,自己得补"\n",否则多条记录挤在同一行 - 写入数组时,
file_put_contents会自动implode('', $array),但仅限一维数组;传二维数组会报 Warning 并写入空字符串 - 权限问题常被忽略:PHP 进程用户(如 www-data)必须对目录有写权限,而不仅是文件——Linux 下新建文件的属组继承自目录,不是父进程
按行处理大文件,用 fgets 而不是 file
file() 把整文件载入内存再切分成数组,100MB 日志直接 OOM;fgets() 每次只读一行,内存占用稳定在 KB 级。
立即学习“PHP免费学习笔记(深入)”;
- 必须配合
fopen使用,打开后记得fclose,否则 fd 耗尽会卡住后续请求 -
fgets返回的每行末尾自带\n,trim()前要确认是否真要删——比如解析带空格缩进的配置时删了会破坏结构 - 遇到二进制内容或非 UTF-8 编码(如 GBK 日志),
fgets可能截断中文,此时得改用fread($fp, 4096)自行按边界解析 - Windows 换行符
\r\n在 Linux 环境下读出来仍是完整两个字符,str_replace("\r\n", "\n", $line)不是必须,但统一处理更稳妥
真正麻烦的从来不是函数怎么调用,而是路径是否真实存在、权限是否到位、并发时有没有锁、编码是否一致——这些地方一错,错误信息往往藏在 error_log 里,而不是屏幕上。



















