
本文详解如何在 php 中向文件写入数组数据时防止重复追加,涵盖清空重写、内容比对去重两种策略,并提供可直接运行的代码示例与关键注意事项。
在使用 file_put_contents() 向文件写入数据时,若反复执行且始终传入 FILE_APPEND 标志,就会导致历史数据不断累积——正如问题中所示:每次运行脚本,Fanny, 1034 等记录都被重复追加,造成数据冗余。根本原因在于:FILE_APPEND 仅负责“追加”,不负责“判断是否已存在”。
✅ 方案一:覆盖写入(适用于每次全量更新场景)
若每次运行脚本都应以当前 $result 数组为唯一权威数据源(即旧数据完全失效),最简单高效的方式是移除 FILE_APPEND,让 file_put_contents() 默认以覆盖模式写入:
$dir = "C:/Users//data"; if (!is_dir($dir)) { mkdir($dir, 0777, true); // 添加第三个参数 true 支持递归创建 } $dataLines = []; foreach ($result as $item) { // 注意:原代码中误用了 $data(应为 $asset),且部分键名为 asset_no $name = $item[0]['name'] ?? ''; $asset = $item[0]['asset'] ?? $item[0]['asset_no'] ?? ''; $dataLines[] = "$name, $asset"; } // 覆盖写入(无 FILE_APPEND)→ 自动清除旧内容 file_put_contents("$dir/data", implode("\r\n", $dataLines) . "\r\n");
✅ 优点:简洁、高效、无读取开销;
⚠️ 注意:确保 $result 始终包含完整最新数据集,否则会丢失未包含的条目。
✅ 方案二:智能去重追加(适用于增量更新或需保留历史逻辑)
若需保留文件中已有数据,并仅追加 $result 中尚未存在的新记录(例如按 name 或 name+asset 组合去重),则需先读取并解析现有内容:
$filePath = "$dir/data";
$existingData = [];
// 尝试读取并解析已有数据(按行分割,提取 name 和 asset)
if (file_exists($filePath)) {
$lines = array_filter(array_map('trim', file($filePath)));
foreach ($lines as $line) {
if (preg_match('/^([^,]+)\s*,\s*(.+)$/', $line, $matches)) {
$existingData[] = [
'name' => trim($matches[1]),
'asset' => trim($matches[2])
];
}
}
}
// 构建去重后的待写入数据
$newLines = [];
foreach ($result as $item) {
$name = $item[0]['name'] ?? '';
$asset = $item[0]['asset'] ?? $item[0]['asset_no'] ?? '';
// 判断是否已存在(此处按 name + asset 联合去重)
$exists = false;
foreach ($existingData as $exist) {
if ($exist['name'] === $name && $exist['asset'] === $asset) {
$exists = true;
break;
}
}
if (!$exists) {
$newLines[] = "$name, $asset";
}
}
// 追加新记录(仅新增部分)
if (!empty($newLines)) {
file_put_contents($filePath, implode("\r\n", $newLines) . "\r\n", FILE_APPEND | LOCK_EX);
}✅ 优点:精准控制增量,兼容历史数据;
⚠️ 注意:LOCK_EX 可防止并发写入冲突;正则解析需适配实际数据格式;大规模数据建议改用数据库或 JSON 存储提升可维护性。
? 总结与最佳实践
- 不要滥用 FILE_APPEND:它不解决“是否重复”问题,只解决“写在哪”的问题;
- 明确业务语义:全量刷新 → 用覆盖写入;增量同步 → 先读后比再追加;
- 健壮性增强:添加 is_writable() 检查、异常捕获、路径安全过滤(如避免 ../);
- 进阶建议:长期项目中,推荐将结构化数据存为 JSON 文件(file_put_contents(..., json_encode($result))),便于序列化/反序列化与跨语言兼容。
通过合理选择写入策略并修正原始代码中的变量名错误($data → $asset)和键名兼容处理(asset / asset_no),即可彻底解决重复写入问题。
立即学习“PHP免费学习笔记(深入)”;











