Как вставить строку перед последним символом в большом файле - PullRequest
0 голосов
/ 13 марта 2020

У меня очень большой файл, состоящий из одной строки. Из-за размера файла я не хочу читать всю строку в память.

Последний символ всегда будет закрывающей скобкой ], так как эта строка является массивом 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 неправильное место или проблема в другом месте. Спасибо за любую помощь.

Ответы [ 2 ]

2 голосов
/ 13 марта 2020

Из документов (выделено мной):

a+: открыто для чтения и письма; поместите указатель файла в конец файла. Если файл не существует, попытайтесь создать его. В этом режиме функция fseek () влияет только на позицию чтения, записи всегда добавляются.

Вместо этого используйте режим r+, вместо fstat вы можете выполнить:

fseek($fh, -1, SEEK_END);
0 голосов
/ 13 марта 2020

Пожалуйста, попробуйте следующий код, чтобы получить ваше решение, я проверил, и он отлично работает ...

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());
}
...