如何在大文件的最后一个字符之前插入一个字符串

How insert a string before last character in a large file

我有一个非常大的文件,其中包含一个字符串。由于文件的大小,我不想将整个字符串读入内存。

最后一个字符将始终是右括号 ],因为此字符串是一个 json 数组。我想在右括号之前插入一个小的 json 对象(表示为字符串)。我已经看到了一些想法,但无法使任何事情发挥作用。

如您所见,我正在尝试打开文件并使用 fseek 将文件指针移动到 ] 的前面。然后我尝试将新字符串写入该位置的现有字符串。

然而,这样做的效果只是将新字符串追加到现有字符串的末尾,这不是我想要的。

作为一个简化示例,假设文件开始时包含以下字符串:

[{"name":"alice","city":"london"}]

然后我想使用此代码将第二个人添加到此列表中:

$new_person = ",{\"name\":\"bob\",\"city\":\"paris\"}";

$filename = "people.json";
$fh = fopen($filename, "a+");
$filesize = filesize($filename);
$stat = fstat($fh);
fseek($fh, $stat[$filesize]-1);
fwrite($fh, $new_person);
fclose($fh); 

但我最终得到的是一个包含以下字符串的文件:

[{"name":"alice","city":"london"}],{"name":"bob","city":"paris"}

我的 PHP 技能很糟糕。我不知道我的 fseek 是否指向了错误的位置,或者问题是否出在其他地方。感谢您的帮助。

来自 docs(强调我的):

a+: Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it. In this mode, fseek() only affects the reading position, writes are always appended.

改用r+模式,而不是fstat你可以这样做:

fseek($fh, -1, SEEK_END);

请尝试以下代码来获得您的解决方案,我已经测试过并且它工作正常...

try{
    $new_person = ",{\"name\":\"bob\",\"city\":\"paris\"}]";
    $filename = "people.json";
    $fh = fopen($filename, "a+");
    $stat = fstat($fh);
    ftruncate($fh, $stat['size'] - 2);
    fwrite($fh, $new_person);
    fclose($fh); 
}catch(Exception $exc){
    echo($exc->getMessage());
}