Эта тема на forum.dklab.ru


Константин Жинько [tIT]: fopen("r+") или я что-то не понимаю %
Что-то не соображу %
Задача -- дописывать в начало файла строку.

Вот, что накалякал:

//кусок конструтора
//Создаем лог, если нет
@fclose(fopen($this->logfile, "a+"));
//Открываем лог для записи
$this->logd = fopen($this->logfile, 'r+');
}

//Помещает в лог сообщение об ошибке с трассировкой
function err($str){

$trace = debug_backtrace();

$line = date("H:i:s");
$line .= ' '.$_SERVER['REMOTE_ADDR'];
$line .= ' '.$trace[0]['file'];
$line .= ' '.$trace[0]['line'];
$line .= ' "'.$str.'"';
$line .= "\n";
flock($this->logd, LOCK_EX);
fwrite($this->logd, $line);
}

Вызываю err() первый раз -- создается файл с сообщением.
Вызываю второй -- старая строка стирается, новая добавляется %
Как быть?
Владимир Хоменко:
tIT, а вы хотели, чтобы r+ писало в начало файла строчку, а остальные сдвигало к концу файла?

Это было бы просто замечательно, но так у вас не получится.

Решение только одно: все считать в массив из файла, добавить в начало массива нужную строку и записать все назад в файл.
Константин Жинько [tIT]:
tIT, а вы хотели, чтобы r+ писало в начало файла строчку, а остальные сдвигало к концу файла?
Хотел.
Ну да -- утопия! =))
Совсем торможу! =)
+1
Юрий Насретдинов:
tIT
А еще лучше использовать a+ - это самый надежный способ. Правда, в начало файла он записать ничего, естественно, не даст (а хотелось бы, чтоб файловая система такое позволяла, это же в принципе не так трудно реализовать...)
Владимир Хоменко:
yUAC, а как вы себе это представляете с точки зрения файловой системы?

Реализовать это довольно проблематично, как мне кажется. Это ж чтоб записать в начало большого файла, надо сдвинуть весь файл на длину записываемой строки в памяти. Вообщем, если бы это легко было бы реализовать, это бы уже реализовали, IMHO.
Юрий Насретдинов:
как вы себе это представляете с точки зрения файловой системы?
Хм, если мне не изменяет память, то в файловой системе хранится список кластеров, из которых состоит каждый файл. ИМХО, если записывать часть данных в другие кластеры, а потом просто добавить их куда-нибудь в середину, или начало списка, это будет намного быстрее, чем целиком переписывать весь файл, разве не так?
Евгений Галашин:
это будет намного быстрее, чем целиком переписывать весь файл, разве не так?
А кто сказал, что данные займут _целый кластер_?
Дмитрий Котеров:
a+ - довольно опасный режим. В какой-то версии FreeBSD в нем можно только дописывать в конец файла, fseek() не срабатывает.
Универсальный вариант - такой:


@fclose(fopen($fn="file", "a+")); // создаем пустой, если не было
$f = fopen($fn, "r+");
flock($f, LOCK_EX);
...
fclose($f);

Константин Жинько [tIT]:
Универсальный вариант - такой:
Так и делаю...
В принципе на маленьких файлах быстро работает... А вот если в файле 4895К... Вобщем мне лень было ждать, как это банально ни звучит =)
Юрий Насретдинов:
кто сказал, что данные займут _целый кластер_
Никто не говорил. Тем не менее, если размер кластера не очень большой, или размер вставляемых данных достаточно велик, такая вещь вполне может прокатить. В общем, видимо разработчикам файловых систем было не до того =). Надо будет разработчикам ufs написать, вдруг добавят =)
Константин Жинько [tIT]:
Тем не менее, если размер кластера не очень большой, или размер вставляемых данных достаточно велик, такая вещь вполне может прокатить.
Нельзя всех под одну гребенку-то *)

Эта тема на forum.dklab.ru