使用PHP打开修改JSON文件时fopen的r+/w+/a+模式选择问题
关于PHP fopen模式适配JSON文件更新的解答
三个候选模式的排除与选择
你筛选的三个模式中,仅r+适配你的需求,另外两个模式的特性验证如下:
w+:截断操作发生在文件打开的瞬间,只要调用fopen时指定该模式,原有内容会被立即清空,你还没读取旧的JSON数据就会拿到空内容,直接排除。a+:你的判断完全正确,该模式强制所有写入操作定位到文件末尾,即使手动移动指针到开头也不会生效,无法实现整个JSON文件的覆盖更新,直接排除。r+:打开文件时指针定位在开头,写入操作是直接覆盖指针位置的原有内容,不存在自动插入逻辑。你需要注意的坑是:如果新JSON内容长度短于旧内容,覆盖后文件末尾会残留旧内容的多余字符,导致JSON解析失败,处理方法是写入新内容后手动截断文件多余部分。
基于r+的标准实现流程
完整的操作需要加独占锁避免并发写入异常,步骤如下:
- 用
r+模式打开JSON文件,调用flock($fp, LOCK_EX)加独占锁 - 读取文件全量内容,解析为PHP数组
- 用
array_unshift将新博文信息插入到数组开头 - 将新数组编码为JSON字符串
- 调用
rewind($fp)将文件指针移回开头 - 写入新的JSON字符串
- 调用
ftruncate($fp, ftell($fp))截断指针后残留的旧内容 - 解锁、关闭文件句柄
更适配小体量场景的简化实现
你当前的场景文件体积小、无高并发压力,完全可以用更简单的读写函数组合,避免fopen的模式坑:
// 定义JSON文件路径 $jsonPath = __DIR__ . '/posts.json'; // 读取原有内容,解析失败时默认用空数组 $postList = json_decode(file_get_contents($jsonPath), true) ?: []; // 构造新博文数据 $newPost = [ 'title' => '新博文标题', 'author' => '作者名', 'date' => date('Y-m-d H:i:s'), 'link' => '/新文章目录路径/' ]; // 插入到数组开头 array_unshift($postList, $newPost); // 写回文件,保留格式、不转义中文 file_put_contents( $jsonPath, json_encode($postList, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) );
该方案代码量少、可读性高,完全满足你练习文件操作和JSON处理的需求。
内容的提问来源于stack exchange,提问作者Anthony LoPrimo
相关产品推荐
相关产品推荐

