За последние 24 часа нас посетили 51320 программистов и 1758 роботов. Сейчас ищут 754 программиста ...

Как правильно оптимизировать код работы со строками в файле?

Тема в разделе "PHP для новичков", создана пользователем viv, 29 ноя 2011.

  1. viv

    viv Активный пользователь

    С нами с:
    19 ноя 2011
    Сообщения:
    33
    Симпатии:
    0
    Всем привет)

    Подскажите пожалуйста, как можно оптимизировать этот код:
    PHP:
    1.  
    2. <?php
    3. $file_array = file("links.txt");
    4. $max_colichestvo = count($file_array);
    5. $sluchainiy_link = rand(0, $max_colichestvo);
    6. print $file_array[$sluchainiy_link];
    7. ?>
    8.  
    Говорят я им положил сайт.

    Его назначение, это выводить на сайте каждый раз при перезагрузке страницы, другую ссылку. Ссылок в файле более 8000.

    Я думаю, что система грузиться массивом из 8000 элементов. Наверное нужно как то просто подсчитать соличество строк в файле, затем, рандомно выбрать строку и открыть файл и вытащить только эту строчку.
    Но что то не пойму, ведь все равно придется использовать функцию file() и получается опять массив создается из 8000.

    Что то я подзапутался, можете помочь направлением? :)
     
  2. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    хранить в БД :)
     
  3. viv

    viv Активный пользователь

    С нами с:
    19 ноя 2011
    Сообщения:
    33
    Симпатии:
    0
    Это отпадает к сожалению (( Может есть идеи?
     
  4. Mr. T

    Mr. T Активный пользователь

    С нами с:
    10 ноя 2010
    Сообщения:
    733
    Симпатии:
    0
    Адрес:
    Украина, г. Киев
    PHP:
    1. <?php
    2. $array = file ('filename.txt');
    3. echo $array[array_rand (file ('filename.txt'))];
    , но не думаю, что на скорость это повлияет, количество строк будет меньше...
     
  5. viv

    viv Активный пользователь

    С нами с:
    19 ноя 2011
    Сообщения:
    33
    Симпатии:
    0
    Мне скорость не очень важна, главное строк чтоб было меньше. Но здесь опять массив в переменной $array у Вас, опять туда залетят все 8000 строк из файла, у меня посещаемость высокая несколько сотен тысяч уников, и для каждого формируется 8000 строк в массиве. Это как то не очень хорошо. Может еще есть варианты?
     
  6. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    Mr. T
    Тут как раз затратная операция - чтение из файла. А ты её 2 раза выполняешь.

    PHP:
    1.  
    2. <?php
    3.  
    4. $file_array = file("links.txt");
    5. echo array_rand($file_array);
    viv
    В случае работы с файлом - никак. Медленная операция - именно чтение.
     
  7. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    Можно придумать что-то типа

    1) читаем файл полностью.
    2) выбираем с помощью array_rand($file_array, 100) - например 100 случайных строк.
    3) складываем в еще один файл.
    4) из этого файла читаем только 1 строку, и её удаляем
    5) если этот доп файл пустой - повторяем с шага 1
     
  8. Mr. T

    Mr. T Активный пользователь

    С нами с:
    10 ноя 2010
    Сообщения:
    733
    Симпатии:
    0
    Адрес:
    Украина, г. Киев
    tommyangelo, так и есть, сразу написал в одну строку неверно, потом правил, но видно не заметил :) Лучше тут все же завести таблицу в БД, один раз записать в нее данные и дальше работать с ней. Я за БД...
     
  9. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    Mr. T
    Я тоже, тем более не обязательно же mysql использовать, есть sqlite
     
  10. viv

    viv Активный пользователь

    С нами с:
    19 ноя 2011
    Сообщения:
    33
    Симпатии:
    0
    Да в бд конечно лучше)) Только этот код мы отдаем партнерам, которые на своих сайтах размещают. А они не хотят в базу заносить(( Вот и приходится плясать.

    А можно попробовать вот так:

    к примеру использовать рандомный fseek.
    Найти возврат каретки $position.
    Вывести все символы от $position до конца строки (опять ищем возврат каретки)

    Что Вы про это думаете?
     
  11. viv

    viv Активный пользователь

    С нами с:
    19 ноя 2011
    Сообщения:
    33
    Симпатии:
    0
    Попробовал несколько вариантов:

    1)
    PHP:
    1.  
    2. <?php
    3.  $fp = fopen('links.txt', 'r');
    4.  $rand = rand(0, 81314);
    5.       while ($fp){
    6.         $link = fgets($fp);
    7.          $k++;      
    8.             if($k==$rand) {
    9.                  print_r($link);
    10.                  flush();
    11.                  exit();
    12.                  fclose('links.txt');
    13.              }
    14.          $d = 0;                            
    15.          fseek($fp, 0, SEEK_CUR);
    16.          }
    17. ?>
    18.  
    2)
    PHP:
    1.  
    2. <?php
    3. $file_array = file("links.txt");
    4. $e = array_rand($file_array);
    5. print $file_array[$e];
    6. ?>
    7.  
    3)
    PHP:
    1.  
    2. <?php
    3. $file_array = file("links.txt");
    4.  $max_colichestvo = count($file_array);
    5.  $sluchainiy_link = rand(0, $max_colichestvo);
    6.  print $file_array[$sluchainiy_link];
    7. ?>
    8.  
    Результат: 1) Всех больше загрузил процессор на компе, а 2) и 3) почти одинакого работают.

    Почему 1й вариант нагружает проц? Ведь я не создаю массив, а только пробегаю по файлу. Может я не правильно воспользовался функцией fseek?
     
  12. Mr. T

    Mr. T Активный пользователь

    С нами с:
    10 ноя 2010
    Сообщения:
    733
    Симпатии:
    0
    Адрес:
    Украина, г. Киев
    Как уже было написано выше - дело в чтении файла...
     
  13. viv

    viv Активный пользователь

    С нами с:
    19 ноя 2011
    Сообщения:
    33
    Симпатии:
    0
    Видимо без БД все таки не обойтись. Уж слижком большой файл получается. Жаль.
     
  14. Mamont

    Mamont Активный пользователь

    С нами с:
    5 дек 2010
    Сообщения:
    183
    Симпатии:
    0
    Не слушай их. Тести ;)
    PHP:
    1. <?php
    2. $fname = 'data.txt';
    3. $f = fopen( $fname, 'r' ); //
    4. fseek( $f, rand(0,filesize($fname)-1) );
    5. fgets( $f );
    6. do {
    7.    if( fEoF($f) ) fseek( $f, 0 );
    8.    $result = fgets( $f );
    9. } while( trim($result)=='' );
    10.  
    11. echo $result;
    12.  
     
  15. viv

    viv Активный пользователь

    С нами с:
    19 ноя 2011
    Сообщения:
    33
    Симпатии:
    0
    Спасибо за код :) Ни как все его не протестю, со временем напряжно стало ((, но обязательно попробую и отпишусь о результатах.
     
  16. viv

    viv Активный пользователь

    С нами с:
    19 ноя 2011
    Сообщения:
    33
    Симпатии:
    0
    Mamont

    Спасибо дружище, код работает просто супер! Осталось только протестировать на боевом сервере)
    И жаль конечно, что у самого не получилось :(
     
  17. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Я бы сделал так.
    Файл с данными сделал бы типа двумерного массива, ширина которого - максимально нужное количество символов в строке. Если в какой-то строке запись меньше макс. ширины, то остаток заполнять пробелами. Файл получится большим, но с предсказуемыми позициями.
    В отдельном файле хранить количество записей. Всего одно число.
    Сначала прочитать его, найти rand-омное число.
    Затем умножением числа на на макс. ширину находим позицию начала строки в файле данных.
    Далее, как обычно с помощью fopen(), fseek() и fgets() читаем строку и удаляем пробелы с помощью rtrim().
     
  18. viv

    viv Активный пользователь

    С нами с:
    19 ноя 2011
    Сообщения:
    33
    Симпатии:
    0
    Хм, а что, интересный вариант, спасибо за идею))))
    нужно будет тоже потестить.