За последние 24 часа нас посетили 23168 программистов и 1660 роботов. Сейчас ищет 831 программист ...

Поиск и сортировка в большом файле

Тема в разделе "PHP для новичков", создана пользователем блудный сын, 26 ноя 2008.

  1. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    У меня есть большие текстовые файлы размером от 1до 100МБ, в которых написаны слова, каждое слово с новой строчки, вот примерно так:
    Код (Text):
    1.  
    2. дерево
    3. листья
    4. осень
    5. ....
    6. ....
    7. листопад
    Нужно отсортировать слова в файле по алфавиту и сделать поиск среди слов файла, например с нахождением всех слов имеющих корень "лист".
    Думал стандартно воспользоваться для этого функцией file():
    PHP:
    1.  
    2. $content=file("file1.txt");
    3. sort ($content);
    4.  
    но неожиданно возникла проблема, функция не открывает файлы с размером больше 1 МБ, и выдает примерно такие ошибки: Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 35 bytes) in С:\... on line 10 Странная ошибка и странно ее видеть для файла с размером далекого до 8МБ...

    Подскажите, в сторону каких функций смотреть, чтобы смочь работать с большими файлами?
     
  2. Geqsogen

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

    С нами с:
    7 ноя 2008
    Сообщения:
    11
    Симпатии:
    0
    Возможно это:
    fgets -- Читает строку из файла
    Код (Text):
    1. <?php
    2. $handle = fopen("/tmp/inputfile.txt", "r");
    3. while (!feof($handle)) {
    4.     $buffer = fgets($handle, 4096);
    5.     echo $buffer;
    6. }
    7. fclose($handle);
    8. ?>
    но все равно это через каку...
     
  3. Greg1978

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

    С нами с:
    18 окт 2008
    Сообщения:
    484
    Симпатии:
    0
    Адрес:
    class SenjorUser{}
    fopen();
    fgets();
     
  4. free-bits

    free-bits Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    296
    Симпатии:
    0
    Адрес:
    г. Красноярск
    A если ReadFile или file_get_contents?
     
  5. free-bits

    free-bits Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    296
    Симпатии:
    0
    Адрес:
    г. Красноярск
    Поиск - array_search
     
  6. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    Это код по кусочкам файл читает, но как отсортировать слова всего файла по алфавиту? Максимум я получается могу отсортировать слова в этом кусочке...
     
  7. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    А как превратить большой файл в массив?
     
  8. free-bits

    free-bits Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    296
    Симпатии:
    0
    Адрес:
    г. Красноярск
    Можно так explode("\n", $file) если она поддерживает большие файлы=)
     
  9. Петр

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

    С нами с:
    20 мар 2006
    Сообщения:
    1.253
    Симпатии:
    0
    Адрес:
    Центр Вселенной
    Е-мое ну не чудаки ли вы?
    Там памяти не хватает.

    Нужно менять алгоритм.
     
  10. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    А кто она? Вот сделал так:
    PHP:
    1.  
    2. $bufer=readfile("file1.txt", "r");
    3.    
    4. $bufer=explode("\n", $bufer);
    5.  
    6. sort ($bufer);
    7.  
    8. print_r ($bufer);
    9.  
    Код работает но не так как ожидается. Наблюдаю две странности: во-первых результат выводится не отсортированным, а во вторых переменная $bufer по всей видимости в массив не попала, т.к. в конце вывода имею:
    Код (Text):
    1.  
    2. ...
    3. листопад
    4. Array
    5. (
    6.     [0] => 1803405
    7. )
    даже три странности, в массив переменная $bufer не попала, но с этой строчкой print_r ($bufer); как-то выводится...
     
  11. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    А есть идеи?
     
  12. free-bits

    free-bits Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    296
    Симпатии:
    0
    Адрес:
    г. Красноярск
    Я имел в виду она - то бишь функция)
     
  13. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Я так думаю, что надо участками сканировать файл при поиске. В каждом участке искать наиболее подходящее слово. Потом искать среди собранных слов со всех участков.

    Для увеличения скорости надо делать индексные файлы. Вот так и ползет приближение к СУБД.

    Для сортировки, скорее всего придется создавать для каждой буквы по файлу, а потом их соединять, если начальный файл 100 мб весит.
     
  14. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
  15. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    решение "в лоб" - запихать все в SQLite
    PHP:
    1. <?
    2. // php.ini: memory_limit = 1M
    3.  
    4. $fn = 'test.txt'; // size 8 672 155 bytes
    5. $dbFn = "$fn.sqlite";
    6.  
    7. if (file_exists($dbFn)) unlink($dbFn);
    8. $db = new PDO("sqlite:$dbFn");
    9. $db->beginTransaction();
    10. $db->exec("CREATE TABLE t(t)");
    11. $fp = fopen($fn, 'r');
    12. while(!feof($fp)) {
    13.     $value = fgets($fp);
    14.     $value = trim($value);
    15.     $value = $db->quote($value);
    16.     $db->exec("INSERT INTO t(t) VALUES($value)");
    17. }
    18. $db->commit();
    19. fclose($fp);
    20.  
    21. // получение с сортировкой
    22. $q = $db->query("SELECT t FROM t ORDER BY t", PDO::FETCH_NUM);
    23. foreach ($q as $value) {
    24.     $value = $value[0];
    25.     echo $value,"\n";
    26. }
    27.  
    28. unset($db);
    29. unlink($dbFn);
     
  16. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    А я удалил mysql и уже несколько месяце его не юзаю :(
    А если добавить до 100МБ? Потянет на файлах и стандартных функциях?
     
  17. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    !=
     
  18. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    Заглянул в php.ini, у меня там memory_limit = 8M. Но почему же уже с файлами в полтора метра, выдает ошибку Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 16 bytes)
    И что означает это: (tried to allocate 16 bytes) Что за 16 байтов?
     
  19. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    Им я вообще не пользовался :( Что же делать?
     
  20. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    Как же я мог выйти за этот предел если файл полтора метра. Вот этот начальный исходник, которым пытаюсь хоть как-то работать с большими файлами:
    PHP:
    1.  
    2. <?php
    3. $handle = fopen("file1.txt", "r");
    4. while (!feof($handle)) {
    5.     $bufer = fgets($handle);
    6.     $buf[]=$bufer;
    7.     }
    8. fclose($handle);
    9. sort($buf);
    10. print_r ($buf);
    11. ?>
    12.  
     
  21. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    чем не устраивает выше приведенный код?
     
  22. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    все просто: PHP не хранит данные 1 к 1, они занимают больше, иногда гораздо больше
    PHP:
    1. <?
    2. $size = memory_get_usage();
    3. $str = str_repeat(' ', 1000);
    4. echo memory_get_usage()-$size;//1276
     
  23. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    Тем что у меня нет SQLite и я с ним не работал :(
     
  24. блудный сын

    блудный сын Активный пользователь

    С нами с:
    18 июн 2008
    Сообщения:
    632
    Симпатии:
    0
    В вашем примере увеличение памяти на 27%, а в моем в разы (файл 1,5 метра, а мне не хватает 8 МБ). Как то уж слишком :(
     
  25. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    факты:
    PHP:
    1. <?
    2. $a = array();
    3. $size = memory_get_usage();
    4. for($i = 0; $i < 1000; $i++) $a[] = ' ';
    5. echo memory_get_usage()-$size;//132632 // в 132 раза