Всем привет! Мне нужно сделать функцию которая будет читать первую строку файла и удалять ее. Все просто, реализовал я примерно так. Код (Text): function one_str($file) { $array = file($file); $str = $array['0']; unset($array['0']); file_put_contents($file, implode('', $array)); return $str; } Проблема в том что этот скрипт должен работать с большими тхт файлами, и можно было запускать его с различными гет параметрами одновременно. Я понял что мне нужно реализовать блокировку с помощью функции flock и использовать вместо функции file функции построчного чтения файла, но не особо в этом силен, пока только разбираюсь, а сделать кровь из носа нужно быстрее. Плз подскажите как это реализовать с помощью функций построчного чтения, чтобы можно было работать с большими файлами.
При каждом запросе скрипта нужно удалять по строке? Если нужно удалять первую строку так, чтобы все остальные строки подвинулись вверх, будто удалённой строки и не было вовсе, то работать будет медленно хоть с функцией file и file_put_contents, хоть с fopen, т.к. сдвигаются все символы. Чем больше файл, тем медленней эта операция. Можно попробовать просто удалять символы, не сдвигая остальные (если понимаете, о чем речь). Можно вообще ничего не удалять, а только запоминать позицию, на которой остановились в последний раз, и с которой начать чтение. Расскажите хоть, что делаете. Может, у кого возникнет идея, как лучше реализовать. Мне кажется, вы делаете что-то вроде чата. Так?
Вот пример (не релизный ещё, нет блокировки), как можно читать большой файл строка за строкой, ничего не удаляя. Среднее время работы скрипта 0.001 сек. мало зависит от размера файла (тестил на файле в 522 Mb). Код (PHP): <?php $handlePos = @fopen('pos.txt', 'r+');//открываем файл с последним положением if($handlePos){ if (($buffer = fgets($handlePos, 10)) !== false) { $startPos=(int)$buffer; if($startPos<0) $startPos=0; $handle = @fopen('file.txt', 'rb'); if($handle){ $buffer=''; $newPos=$startPos; fseek($handle, $startPos, SEEK_SET);//указатель в положение if (($buffer = fgets($handle, 5000)) !== false) {//попытка чтения строки echo '<div>read line:<br/>',$buffer,'</div>';//прочитали строку $newPos=ftell($handle);//оказались в позиции } fclose($handle); if($newPos!=$startPos){ rewind($handlePos); fwrite($handlePos, sprintf('%09d', $newPos));//записываем позицию, на которой остановились } } fclose($handlePos); } }else{ echo 'что-то с файлом pos.txt'; } В файле pos.txt сохраняется число - последняя позиция. В file.txt 600 тысяч строк (параграфов).
что именно? =) сандро спалился что юзает ссд, т.к. на хардах 7мс хорошее время доступа. ну или кеш рулит, ага.
Если нужно узнать первую строку указанного файла и удалить ее, можно попробовать циклом for после первого полученного элемента завершить цикл и получить строку. А дальше когда строка уже получена через: Код (PHP): file_put_contents($file,trim(str_replace($string,'',file_get_contents($file),1))); Перезаписать файл.
Проверил такой вариант: Код (PHP): $file='file.txt'; $arrayLine=file($file); if(1<=sizeof($arrayLine)) { if(false!==file_put_contents($file,trim(preg_replace("/{$arrayLine[0]}/",'',join('',$arrayLine),1)))) { echo'Success!'; } else { echo'Error!'; } }
Код (PHP): function pop_first_line() { $fn = './file.txt'; $fn_tmp = './file.tmp'; // $fh = fopen($fn, 'r'); if ($fh) { // show first line if (!feof($fh)) { echo fgets($fh); } // save file without first line $fh_tmp = fopen($fn_tmp, 'w'); if ($fh_tmp) { while (!feof($fh)) { fwrite( $fh_tmp, fgets($fh) ); } close($fh_tmp); } close($fh); } rename($fn_tmp,$fn); }
ну вот исандро предложил отличное решение БЕЗ ПЕРЕЗАПИСИ файла. Добавлено спустя 26 секунд: Вообще правильный ответ: если возник такой вопрос - пора юзать БД
Не всегда. У меня тоже стояла подобная проблема, когда надо было оперировать построчно с файлами при условии, что БД не приемлема, так как это не просто файлы, а *.php, хранящие довольно объемистую инфу, частота обновления которой сверхредкая, а частота обращения - сверхвысокая. Файлы описывают деревья компонентов и их параметры. Без аккселератора скорость работы не ниже, чем с БД. С аккселератором же... Но это частный извращенный случай. При хранении просто инфы да, лучше, приятнее и удобнее юзать БД. Добавлено спустя 51 секунду: Как я понял, там обход 500-метрового файла за 1мс происходил, судя по показаниям, не?
ОМГ. Глаза открой. Зачем тогда вообще нужно будет-это, если перезаписи нет? Ах, ну да... Файлы научились бегать и питаться, они теперь сами умеют понимать, что нужно убирать 1 строку.
в том варианте перезапись просто НЕ НУЖНА, ибо в отдельном файле хранится смещение до текущей строки.
У меня в php.ini определены два параметра auto_prepend_file="prepend.php" и auto_append_file="append.php". В первом Код (PHP): <?php$_tstart=microtime(true); ob_start(); во втором Код (PHP): <?php $html=ob_get_contents(); ob_end_clean(); echo str_replace('<body>','<body>'.'<div style="position:absolute;left:0;top:0;background:#bbf;width:70px;font-size:10px;">'.number_format(microtime(true)-$_tstart,'4',',','').' sec.</div>',$html); Если в документе есть body, то всегда вижу общее время. Сколько времени занимает чтение файла - не знаю! Потестите, чё! Добавлено спустя 8 минут 25 секунд: Если так важно, можно подробные тесты сделать и поместить в тему "кружок извращенцев" (или как там?). ТС так и не отписался, что он делает.
Сделал замеры своего кода, за какое время считывается одна строка из файла в 523 Mb c 600000 строками. Типичные показатели: Код (Text): время выдачи страницы время чтения строки (+ открытия-закрытия файла) 0,0008 0,0003 0,0014 0,0004 0,0010 0,0003 0,0261 0,0255 //примерно 1 из 10 раз 0,0009 0,0003 и т.д. Так что среднее время будет поболее, чем 0.001, но всё равно хорошие показатели, ящитаю. Диск обычный. Читается по одной строке. Думаешь, кешируется весь файл?
Ммм. Ну вот мне не ясно. Может быть много чего. Мне всё равно, что там с этим скриптом ибо по факту там времени будет в любом случае хватать для выполнения на лету. Но мне очень интересно откуда у тебя 1 мс =)
Так мне тоже интересно, потому и попросил потестить у себя. Хотя, сколько помню, это обычное время, нисколько не удивляет. У меня два диска, система на одном, папки сайтов на другом. Видимо, это тоже играет роль.
не, среднее время доступа можно глянуть в спеках харда. там будет ченить типа 7 мс. я всё же думаю на кеш. я сейчас в отпуске, не хочу тестировать =)) и ноут на ссд