PHP fwrite替换文件行时字符长度变化引发内容异常求助
解决PHP替换TXT文件行时,新字符串过长导致后续内容被截断的问题
这问题我太熟了!你遇到的核心坑点在于**r+模式下的文件写入是字节覆盖,而非插入**。当你定位到目标行的位置后写入更长的字符串,多余的字节会直接覆盖掉下一行开头的内容,就像你看到的,第二行的N被新字符串多出来的字符给覆盖了,所以才变成02;102。
给你两种实用的解决方案,按需选择:
方案1:全文件读入内存修改(适合小文件,比如你的score.txt)
这种方式逻辑最简单,也最不容易出错,适合文件体积不大的场景:
// 读取文件所有行到数组,自动跳过空行和换行符 $lines = file("score.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); $targetId = $_SESSION["id"]; $newScore = $_POST['S']; // 遍历找到目标行并替换 foreach ($lines as &$line) { // 拆分每行的ID和分数 list($currentId) = explode(';', $line); if ($currentId === $targetId) { $line = "$targetId;$newScore"; break; // 找到后就退出循环,提升效率 } } unset($line); // 记得释放引用,避免后续意外修改 // 把修改后的数组重新写入文件,每行加上换行符 file_put_contents("score.txt", implode("\n", $lines) . "\n");
方案2:临时文件逐行处理(适合大文件,避免内存占用过高)
如果你的score.txt以后可能变得很大,不想一次性把所有内容读进内存,可以用临时文件中转的方式:
$targetId = $_SESSION["id"]; $newLine = "$targetId;" . $_POST['S'] . "\n"; // 创建临时文件 $tempFilePath = tempnam(sys_get_temp_dir(), 'score_temp'); $originalHandle = fopen("score.txt", 'r'); $tempHandle = fopen($tempFilePath, 'w'); // 逐行读取原文件,修改后写入临时文件 while (($line = fgets($originalHandle)) !== false) { $currentId = trim(explode(';', $line)[0]); if ($currentId === $targetId) { fwrite($tempHandle, $newLine); } else { fwrite($tempHandle, $line); } } // 关闭文件句柄 fclose($originalHandle); fclose($tempHandle); // 替换原文件 unlink("score.txt"); rename($tempFilePath, "score.txt");
为什么原来的方法会出问题?
再给你补个原理:用r+打开文件时,文件指针停在你定位的目标行起始位置,fwrite会从这个位置开始覆盖写入字节。比如原目标行是N01;99\n(共6个字节),新字符串是N01;100\n(7个字节),多出来的1个字节就会把下一行的第一个字符N给覆盖掉,所以第二行就变成了02;102,这就是你看到的截断现象。
内容的提问来源于stack exchange,提问作者chcswt
相关产品推荐
相关产品推荐

