У меня есть большие текстовые файлы размером от 1до 100МБ, в которых написаны слова, каждое слово с новой строчки, вот примерно так: Код (Text): дерево листья осень .... .... листопад Нужно отсортировать слова в файле по алфавиту и сделать поиск среди слов файла, например с нахождением всех слов имеющих корень "лист". Думал стандартно воспользоваться для этого функцией file(): PHP: $content=file("file1.txt"); sort ($content); но неожиданно возникла проблема, функция не открывает файлы с размером больше 1 МБ, и выдает примерно такие ошибки: Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 35 bytes) in С:\... on line 10 Странная ошибка и странно ее видеть для файла с размером далекого до 8МБ... Подскажите, в сторону каких функций смотреть, чтобы смочь работать с большими файлами?
Возможно это: fgets -- Читает строку из файла Код (Text): <?php $handle = fopen("/tmp/inputfile.txt", "r"); while (!feof($handle)) { $buffer = fgets($handle, 4096); echo $buffer; } fclose($handle); ?> но все равно это через каку...
Это код по кусочкам файл читает, но как отсортировать слова всего файла по алфавиту? Максимум я получается могу отсортировать слова в этом кусочке...
А кто она? Вот сделал так: PHP: $bufer=readfile("file1.txt", "r"); $bufer=explode("\n", $bufer); sort ($bufer); print_r ($bufer); Код работает но не так как ожидается. Наблюдаю две странности: во-первых результат выводится не отсортированным, а во вторых переменная $bufer по всей видимости в массив не попала, т.к. в конце вывода имею: Код (Text): ... листопад Array ( [0] => 1803405 ) даже три странности, в массив переменная $bufer не попала, но с этой строчкой print_r ($bufer); как-то выводится...
Я так думаю, что надо участками сканировать файл при поиске. В каждом участке искать наиболее подходящее слово. Потом искать среди собранных слов со всех участков. Для увеличения скорости надо делать индексные файлы. Вот так и ползет приближение к СУБД. Для сортировки, скорее всего придется создавать для каждой буквы по файлу, а потом их соединять, если начальный файл 100 мб весит.
решение "в лоб" - запихать все в SQLite PHP: <? // php.ini: memory_limit = 1M $fn = 'test.txt'; // size 8 672 155 bytes $dbFn = "$fn.sqlite"; if (file_exists($dbFn)) unlink($dbFn); $db = new PDO("sqlite:$dbFn"); $db->beginTransaction(); $db->exec("CREATE TABLE t(t)"); $fp = fopen($fn, 'r'); while(!feof($fp)) { $value = fgets($fp); $value = trim($value); $value = $db->quote($value); $db->exec("INSERT INTO t(t) VALUES($value)"); } $db->commit(); fclose($fp); // получение с сортировкой $q = $db->query("SELECT t FROM t ORDER BY t", PDO::FETCH_NUM); foreach ($q as $value) { $value = $value[0]; echo $value,"\n"; } unset($db); unlink($dbFn);
А я удалил mysql и уже несколько месяце его не юзаю А если добавить до 100МБ? Потянет на файлах и стандартных функциях?
Заглянул в 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 байтов?
Как же я мог выйти за этот предел если файл полтора метра. Вот этот начальный исходник, которым пытаюсь хоть как-то работать с большими файлами: PHP: <?php $handle = fopen("file1.txt", "r"); while (!feof($handle)) { $bufer = fgets($handle); $buf[]=$bufer; } fclose($handle); sort($buf); print_r ($buf); ?>
все просто: PHP не хранит данные 1 к 1, они занимают больше, иногда гораздо больше PHP: <? $size = memory_get_usage(); $str = str_repeat(' ', 1000); echo memory_get_usage()-$size;//1276
В вашем примере увеличение памяти на 27%, а в моем в разы (файл 1,5 метра, а мне не хватает 8 МБ). Как то уж слишком
факты: PHP: <? $a = array(); $size = memory_get_usage(); for($i = 0; $i < 1000; $i++) $a[] = ' '; echo memory_get_usage()-$size;//132632 // в 132 раза