За последние 24 часа нас посетили 17317 программистов и 1223 робота. Сейчас ищут 1414 программистов ...

Чтение и удаление одной строки из файла

Тема в разделе "PHP для новичков", создана пользователем Nikky, 13 авг 2013.

  1. Nikky

    Nikky Новичок

    С нами с:
    13 авг 2013
    Сообщения:
    2
    Симпатии:
    0
    Всем привет!
    Мне нужно сделать функцию которая будет читать первую строку файла и удалять ее. Все просто, реализовал я примерно так.

    Код (Text):
    1.  
    2. function one_str($file)
    3.     {
    4.     $array = file($file);
    5.     $str = $array['0'];
    6.     unset($array['0']);
    7.     file_put_contents($file, implode('', $array));
    8.     return $str;
    9.     }
    Проблема в том что этот скрипт должен работать с большими тхт файлами, и можно было запускать его с различными гет параметрами одновременно.

    Я понял что мне нужно реализовать блокировку с помощью функции flock и использовать вместо функции file функции построчного чтения файла, но не особо в этом силен, пока только разбираюсь, а сделать кровь из носа нужно быстрее. Плз подскажите как это реализовать с помощью функций построчного чтения, чтобы можно было работать с большими файлами.
     
  2. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    При каждом запросе скрипта нужно удалять по строке?

    Если нужно удалять первую строку так, чтобы все остальные строки подвинулись вверх, будто удалённой строки и не было вовсе, то работать будет медленно хоть с функцией file и file_put_contents, хоть с fopen, т.к. сдвигаются все символы. Чем больше файл, тем медленней эта операция. Можно попробовать просто удалять символы, не сдвигая остальные (если понимаете, о чем речь). Можно вообще ничего не удалять, а только запоминать позицию, на которой остановились в последний раз, и с которой начать чтение.
    Расскажите хоть, что делаете. Может, у кого возникнет идея, как лучше реализовать. Мне кажется, вы делаете что-то вроде чата. Так?
     
  3. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Вот пример (не релизный ещё, нет блокировки), как можно читать большой файл строка за строкой, ничего не удаляя. Среднее время работы скрипта 0.001 сек. мало зависит от размера файла (тестил на файле в 522 Mb).
    Код (PHP):
    1. <?php
    2. $handlePos = @fopen('pos.txt', 'r+');//открываем файл с последним положением
    3. if($handlePos){
    4.     if (($buffer = fgets($handlePos, 10)) !== false) {
    5.         $startPos=(int)$buffer;
    6.         if($startPos<0) $startPos=0;
    7.  
    8.         $handle = @fopen('file.txt', 'rb');
    9.         if($handle){
    10.             $buffer='';
    11.             $newPos=$startPos;
    12.             fseek($handle, $startPos, SEEK_SET);//указатель в положение
    13.             if (($buffer = fgets($handle, 5000)) !== false) {//попытка чтения строки
    14.                 echo '<div>read line:<br/>',$buffer,'</div>';//прочитали строку
    15.                 $newPos=ftell($handle);//оказались в позиции
    16.             }
    17.             fclose($handle);
    18.  
    19.             if($newPos!=$startPos){
    20.                 rewind($handlePos);
    21.                 fwrite($handlePos, sprintf('%09d', $newPos));//записываем позицию, на которой остановились
    22.             }
    23.         }
    24.         fclose($handlePos);
    25.     }
    26. }else{
    27.     echo 'что-то с файлом pos.txt';
    28. }
    В файле pos.txt сохраняется число - последняя позиция. В file.txt 600 тысяч строк (параграфов).
     
    starryknight нравится это.
  4. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    Авесамненько :)
     
  5. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    что именно? =)

    сандро спалился что юзает ссд, т.к. на хардах 7мс хорошее время доступа. ну или кеш рулит, ага.
     
  6. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    То, что я привел в цитате.
    Черт, точно, похоже на то.
     
  7. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Проверьте. Интересно даже.
     
  8. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    я так и не понял. что скрипт имеет доступ к сектору за 1мс?
     
  9. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Если нужно узнать первую строку указанного файла и удалить ее, можно попробовать циклом for после первого полученного элемента завершить цикл и получить строку. А дальше когда строка уже получена через:
    Код (PHP):
    1. file_put_contents($file,trim(str_replace($string,'',file_get_contents($file),1))); 
    Перезаписать файл.
     
  10. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Проверил такой вариант:
    Код (PHP):
    1. $file='file.txt';
    2. $arrayLine=file($file);
    3. if(1<=sizeof($arrayLine)) {
    4.     if(false!==file_put_contents($file,trim(preg_replace("/{$arrayLine[0]}/",'',join('',$arrayLine),1)))) {
    5.         echo'Success!';
    6.     } else {
    7.         echo'Error!';
    8.     }
    9. } 
     
  11. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    Код (PHP):
    1. function pop_first_line() {
    2.   $fn     = './file.txt';
    3.   $fn_tmp = './file.tmp';
    4.   //
    5.   $fh = fopen($fn, 'r');
    6.   if ($fh) {
    7.     // show first line
    8.     if (!feof($fh)) {
    9.       echo fgets($fh);
    10.     }
    11.     // save file without first line 
    12.     $fh_tmp = fopen($fn_tmp, 'w');
    13.     if ($fh_tmp) {
    14.       while (!feof($fh)) {
    15.         fwrite( $fh_tmp, fgets($fh) );
    16.       }
    17.       close($fh_tmp);
    18.     }
    19.     close($fh);  
    20.   }
    21.   rename($fn_tmp,$fn);
    22. }
     
  12. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ну вот исандро предложил отличное решение БЕЗ ПЕРЕЗАПИСИ файла.

    Добавлено спустя 26 секунд:
    Вообще правильный ответ: если возник такой вопрос - пора юзать БД
     
  13. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    Не всегда. У меня тоже стояла подобная проблема, когда надо было оперировать построчно с файлами при условии, что БД не приемлема, так как это не просто файлы, а *.php, хранящие довольно объемистую инфу, частота обновления которой сверхредкая, а частота обращения - сверхвысокая. Файлы описывают деревья компонентов и их параметры. Без аккселератора скорость работы не ниже, чем с БД. С аккселератором же... Но это частный извращенный случай. При хранении просто инфы да, лучше, приятнее и удобнее юзать БД.

    Добавлено спустя 51 секунду:
    Как я понял, там обход 500-метрового файла за 1мс происходил, судя по показаниям, не? :)
     
  14. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    ОМГ. Глаза открой. Зачем тогда вообще нужно будет-это, если перезаписи нет?
    Ах, ну да... Файлы научились бегать и питаться, они теперь сами умеют понимать, что нужно убирать 1 строку.
     
  15. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    в том варианте перезапись просто НЕ НУЖНА, ибо в отдельном файле хранится смещение до текущей строки.
     
  16. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    У меня в php.ini определены два параметра auto_prepend_file="prepend.php" и auto_append_file="append.php".
    В первом
    Код (PHP):
    1. <?php$_tstart=microtime(true);
    во втором
    Код (PHP):
    1. <?php
    2. 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 секунд:
    Если так важно, можно подробные тесты сделать и поместить в тему "кружок извращенцев" (или как там?).
    ТС так и не отписался, что он делает.
     
  17. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Сделал замеры своего кода, за какое время считывается одна строка из файла в 523 Mb c 600000 строками.
    Типичные показатели:
    Код (Text):
    1. время выдачи страницы      время чтения строки (+ открытия-закрытия файла)
    2. 0,0008                        0,0003
    3. 0,0014                        0,0004
    4. 0,0010                        0,0003
    5. 0,0261                        0,0255 //примерно 1 из 10 раз
    6. 0,0009                        0,0003
    7. и т.д.
    Так что среднее время будет поболее, чем 0.001, но всё равно хорошие показатели, ящитаю.

    Диск обычный. Читается по одной строке. Думаешь, кешируется весь файл?
     
  18. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    =(
     
  19. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Ну во-первых может и весь. А во вторых ты рандомно читаешь?
     
  20. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    всё, что есть - в коде выше
     
  21. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    я не вижу кода теста, мне не ясно как ты и сколько раз гоняешь свою функцию.
     
  22. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    А какая разница, если речь о среднем времени? Мне не ясно, что тут может быть не ясно.
     
  23. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Ммм. Ну вот мне не ясно. Может быть много чего. Мне всё равно, что там с этим скриптом ибо по факту там времени будет в любом случае хватать для выполнения на лету.
    Но мне очень интересно откуда у тебя 1 мс =)
     
  24. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Так мне тоже интересно, потому и попросил потестить у себя. Хотя, сколько помню, это обычное время, нисколько не удивляет.
    У меня два диска, система на одном, папки сайтов на другом. Видимо, это тоже играет роль.
     
  25. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    не, среднее время доступа можно глянуть в спеках харда. там будет ченить типа 7 мс. я всё же думаю на кеш. я сейчас в отпуске, не хочу тестировать =)) и ноут на ссд