Одновременно прочитать и перезаписать файл в php

В php функциях fopen или классе SplFileObject существуют режимы(mode) в которых мы открываем файл на одновременное чтение и запись, однако почему-то на практике мало кто пользуется ими так как положено. Обычно пишут типа так:

<?php
$data = file_get_contents('filename');
// действия над $data
// далее file_put_contents
file_put_contents('filename', $data);
// либо fopen + fwrite с блокировками
$open = fopen('filename', 'w');
flock($open, LOCK_EX);
fwrite($open, "data");
flock($open, LOCK_UN);
fclose($open);

По факту файл открывается 2 раза. Во-первых это минус к производительности. Во-вторых, используемая блокировка во втором случае вообще до фонаря. Считав file_get_contents() пять млн. долларов и добавив и записав +1, внезапно можно получить совсем не 6, ибо между чтениями кто-то вклинился и скоммуниздил чего-нибудь. Действия чтения и записи в файл нужно выполнять на одной блокировке.

Приведу пример как одновременно считать, перезаписать файл, обработав и записав данные в первой строке:

<?php
$file = new SplFileObject('filename', 'a+'); // открываем
$file->flock(LOCK_EX); // лочим, уже никто не влезет
$file->rewind(); // перематываем в начало указатель
$data = $file->fgets(); // считываем первую строку
$data = empty($data) ? 1 : ++$data; // выполняем над данными некие действия
$file->ftruncate(0); // очищаем файл
$file->fwrite($data); // записываем новые данные
$file->flock(LOCK_UN); // снимаем блокировку

Вот так правильно.

Оставить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *