Работа с большими файлами (больше 100мб)

Тема в разделе "PHP", создана пользователем PocketDevil, 20 авг 2009.

Статус темы:
Закрыта.
Модераторы: latteo
  1. PocketDevil

    PocketDevil Постоялец

    Регистр.:
    26 янв 2008
    Сообщения:
    92
    Симпатии:
    160
    Требуется открыть и заменить в файле все строки содержащие #name#, скриптом.
    Меня интересует как работать с большими файлами в php.
    Знаю, что оно происходит в несколько этапов и через fopen.
    1) Подсчет общего кол-ва строк
    2) Чтение в цикле по n строк
    3) Замена в прочитанных строках
    Обратно к п.2, и так до конца файла.
    У кого остались примеры. Спасибо
     
  2. betatest

    betatest

    Регистр.:
    3 дек 2007
    Сообщения:
    517
    Симпатии:
    127
    ну во первых 100 мб не такой и большой размер, с ним вполне можно работать

    во вторых - "на лету" проще сделать - читаем - меняем - пишем, правда работать немного дольше будет

    код будет наипримитивнейшим

    кстати файлы с локали читать нужно? или через сеть?
     
  3. PocketDevil

    PocketDevil Постоялец

    Регистр.:
    26 янв 2008
    Сообщения:
    92
    Симпатии:
    160
    Локально
    Но у меня что-то не читает просто через
    fopen
    fread
    fclose

    Процесс висит, но ничего не выводит.
    Файл на 30 метров работает без проблем, а вот больше 100 уже не хочет.
     
  4. betatest

    betatest

    Регистр.:
    3 дек 2007
    Сообщения:
    517
    Симпатии:
    127
    может ограничения где нидь стоят?
    проверь конфиги сервера, пхп.ини и тд
    я там лимит на 500метров выставил - нормально трудится всё
     
  5. antn

    antn Постоялец

    Регистр.:
    11 июл 2009
    Сообщения:
    104
    Симпатии:
    30
    Так читать нужно не сразу все 100 метров, а кусками по несколько кб. Смотри второй аргумент fread или возможно fgets лучше подойдёт (без второго аргумента читает ровно 1 строку до перевода).
     
  6. General Fizz

    General Fizz Боевой Генерал :)

    Регистр.:
    11 апр 2007
    Сообщения:
    753
    Симпатии:
    396
    fgets для чтения из файла вообще не подходит никак кроме разве что самых примитивных случаев, из-за проблем с выделением памяти под читаемую строку.


    Пример:
    PHP:
    $fr=fopen('file.txt','r');


    while(!
    feof($fr)) {

    //////////////////// Замена fgets (если файл в формате windows):
    $str='';
    while(
    "\r"!==($chr=fgetc($fr)) && (!feof($fr))){
        
    $str.=$chr;
    }
    fgetc($fr);
    ///////////////////////////////////////////////////////////////

    ...
    <
    обработка строки $str>
    $str=str_replace(#name#,$value,$str);
    <вывод строки $str например в другой файл>
    ...

    }
    fclose($fr)

    В этом случае файл может быть сколь угодно большим (десятки гигабайт) Дополнительно строки считать не надо, разумные ограничения сервера тоже похуй.
     
    PocketDevil нравится это.
  7. antn

    antn Постоялец

    Регистр.:
    11 июл 2009
    Сообщения:
    104
    Симпатии:
    30
    И какие же проблемы? В сети ничего не нашёл, разумных предположений - ноль.

    Множественная конкатенация может и экономна к памяти, но всё же достаточно трудоёмка при большой длине строки.
     
  8. PocketDevil

    PocketDevil Постоялец

    Регистр.:
    26 янв 2008
    Сообщения:
    92
    Симпатии:
    160
    Генерал, как всегда помог, это то что я и искал.
    Спасибо всем.
     
  9. General Fizz

    General Fizz Боевой Генерал :)

    Регистр.:
    11 апр 2007
    Сообщения:
    753
    Симпатии:
    396
    1. Открываем php.net и читаем описание функции fgets, все проблемы описаны там в комментах.
    2. Проверено лично мной - если в считываемом файле имеются строки большие чем допустим 500 кб, надо под них выделять память в fgets и эта память все равно выделяется независимо от длины считываемой строки, что приводит к большим тормозам в скрипте.
    3. В моем варианте скорость обработки большого файла увеличивается в разы по сравнению с вариантом fgets.

    Проверь сам :p


    Кстати еще мной замечено - при обработке больших файлов/данных (гигабайты) многие библиотечные функции php начинают вести себя неадекватно и приходится их разворачивать. Пример - fgets, serialize.
     
  10. betatest

    betatest

    Регистр.:
    3 дек 2007
    Сообщения:
    517
    Симпатии:
    127
    ХМ, я заинтересовался и проверил

    файл 10гб - просто читаем строки без всякой обработки , с обычным счетчиком строк

    ну собственно вот:

    1 вариант - твой (кстати у тя в коде ; не хватает )
    Open 1 is ok
    Страница сгенерирована за 168.189232 секунд!

    2 вариант - эфгетс
    Open 2 is ok
    Страница сгенерирована за 2.767829 секунд!

    сдается, что не всё так со скоростью, как описано выше
    цифры сами за себя говорят :)
     
Статус темы:
Закрыта.