Реклама на сайте Advertise with us

PHP - как работать с большими файлами

Расширенный поиск по форуму
 
Новая тема Новая тема   
Автор
Поиск в теме:

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 11:16       Ответить с цитатойцитата 

Нужно работать с большими файлами или с большими объемами файлов. Более конкретно, осуществлять по ним разный хитрый поиск.

Файлов у меня 100 000, по несколько кило каждый. Если работать со всеми по очереди, получается медленно. По моим подсчетам:
Прочесть 100 000 файлов по 2k и найти в них строку - 15 секунд.
Прочесть 200Mb (200 файлов по 1Mb) и найти в них строку - 1 секунда.

А если объединить их в один большой файл, получается быстро, но PHP начинает вылетать, когда файл становится больше 10Mb (а я гружу его в массив).

По ряду причин хочется обойтись без MySQL и других БД, работать только средствами PHP.

И там же еще проблема встает. Несколько пользователей могут одновременно писать в один файл. Как сделать так, чтобы они друг другу не мешали, есть готовые рецепты?

Если тебе надо просто подрочить, жми сюда

0
 



С нами с 18.01.06
Сообщения: 322
Рейтинг: 487

Ссылка на сообщениеДобавлено: 29/04/06 в 11:57       Ответить с цитатойцитата 

А зачем грузить его в массив, нельзя разве просто последовательно по одной строке считывать?
Код:

$fp = fopen("path_to_file", "r");
while($line = fgets($fp))
{
       //do something with $line
}
fclose($fp);

5
 

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 12:11       Ответить с цитатойцитата 

Да, это мысль. Хоть и геморройнее, но вполне реально.

Только как мне удастся вставить строку в файл 200Mb? Переписывать и переименовывать?

Если тебе надо просто подрочить, жми сюда

0
 



С нами с 01.10.03
Сообщения: 751
Рейтинг: 318

Ссылка на сообщениеДобавлено: 29/04/06 в 12:13       Ответить с цитатойцитата 

не надо файл одной строкой делать
наоборот, строчек должно быть много
потом читаешь по одной строчке до появления нужного тебе фрагмента

Лучший Хостинг для CJ сайтов!

2
 

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 12:18       Ответить с цитатойцитата 

Да, это я понял. Пусть там будет, допустим, миллион строк по 200 байт. И вот мне понадобилось вставить строку в середину файла. Как это возможно сделать быстро?

Если тебе надо просто подрочить, жми сюда

0
 
+ + +


С нами с 26.04.06
Сообщения: 244
Рейтинг: 82

Ссылка на сообщениеДобавлено: 29/04/06 в 12:24       Ответить с цитатойцитата 

Никак. Только перемещать вторую половину на 200 байт.

Можно еще создать файл индексов подгружать его в массив, производить необходимые действия по изменению порядка строк в большем файле и записывать индексы назад.

3
 

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 12:31       Ответить с цитатойцитата 

Sokira писал:
Можно еще создать файл индексов подгружать его в массив, производить необходимые действия по изменению порядка строк в нем и записывать назад в файл.


То есть, вместо того, чтобы искать через файловую систему, склеить файлы в один большой, и сделать аналог собственной файловой системы в нем?

Надо будет поставить опыт, насколько это ускорит процесс.

А где, кстати, в PHP хранятся максимальные размеры переменной, строки, массива и т.д.?

Если тебе надо просто подрочить, жми сюда

0
 



С нами с 18.01.06
Сообщения: 322
Рейтинг: 487

Ссылка на сообщениеДобавлено: 29/04/06 в 12:41       Ответить с цитатойцитата 

В php.ini переменная memory_limit. По умолчанию она равна 8М, попробуй поменять значение, тоже вариант...

3
 

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 12:46       Ответить с цитатойцитата 



О! Супер! Сейчас поставлю в 200...

Если тебе надо просто подрочить, жми сюда

0
 



С нами с 18.01.06
Сообщения: 322
Рейтинг: 487

Ссылка на сообщениеДобавлено: 29/04/06 в 12:53       Ответить с цитатойцитата 

Петр Кроликов писал:
Да, это я понял. Пусть там будет, допустим, миллион строк по 200 байт. И вот мне понадобилось вставить строку в середину файла. Как это возможно сделать быстро?

Используй временные файлы, переписывай в него все до того места, которое вставить, потом вставка, потом окончание файла, примерно так
Код:

$line_to_insert = "Bla-bla-bla";
$line_after_insert = "Bu-bu-bu";
$fp = fopen("path_to_file", "r");
$tmp = tmpfile();
while($line = fgets($fp))
{
     fwrite($tmp, $line);
     if($line == $line_after_insert)
     fwrite($tmp, $line_to_insert);
}
fclose($fp);
//some actions
$fp = fopen("file_to_write", "w");
fseek($tmp, 0);
while($new_line = fgets($tmp))
{
     fwrite($fp, $new_line);
}
fclose($tmp);//delete temp file
fclose($fp);//file with insert string

3
 

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 13:07       Ответить с цитатойцитата 

Какая-то херь после опытов таинственная icon_sad.gif

Лимит памяти 8М. Тем не менее, командой file() PHP уверенно грузит файл на 200Mb в массив и делает поиск по нему. Как помещается 200Mb в 8-ми выше моего понимания.

По времени выигрыша ни хера нет: ищет гад столько же примерно, сколько и по набору мелких файлов. от 7 до 18 секунд, в зависимости от сложности поставленной задачи.

Так что походу надо просто кэшировать мелкие файлы и ставить мощный сервер icon_sad.gif

Если тебе надо просто подрочить, жми сюда

0
 



С нами с 01.10.03
Сообщения: 751
Рейтинг: 318

Ссылка на сообщениеДобавлено: 29/04/06 в 13:22       Ответить с цитатойцитата 

кстати
что-то мне кажется, что тесты на ХР могут сильно отличаться от боевой работы на NIX, или какая у тебя там ось на сервере стоит
ведь файловые системы устроены и работают по разному
простветите знающие
может имеет смысл поставить виртуальную машину под виндой и на ней тестить?

Лучший Хостинг для CJ сайтов!

2
 



С нами с 18.01.06
Сообщения: 322
Рейтинг: 487

Ссылка на сообщениеДобавлено: 29/04/06 в 13:24       Ответить с цитатойцитата 

Петр Кроликов писал:
Какая-то херь после опытов таинственная icon_sad.gif
Лимит памяти 8М. Тем не менее, командой file() PHP уверенно грузит файл на 200Mb в массив и делает поиск по нему. Как помещается 200Mb в 8-ми выше моего понимания.
По времени выигрыша ни хера нет: ищет гад столько же примерно, сколько и по набору мелких файлов. от 7 до 18 секунд, в зависимости от сложности поставленной задачи.
Так что походу надо просто кэшировать мелкие файлы и ставить мощный сервер icon_sad.gif

Не пробовал file_get_contents()
А с лимитом скорее всего тебе надо сервер перезапустить

3
 

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 13:26       Ответить с цитатойцитата 

proc3nt, запустил твой скрипт. Время выполнения не порадовало (около 16 секунд на 100Mb файле).

Jam, было бы здорово найти где-нибудь живые цифры. Типа, машина такая-то, NIX такой-то, скорость открытия такая-то, чтения такая-то...

Если тебе надо просто подрочить, жми сюда

0
 



С нами с 18.01.06
Сообщения: 322
Рейтинг: 487

Ссылка на сообщениеДобавлено: 29/04/06 в 13:26       Ответить с цитатойцитата 

Jam писал:
кстати
что-то мне кажется, что тесты на ХР могут сильно отличаться от боевой работы на NIX, или какая у тебя там ось на сервере стоит
ведь файловые системы устроены и работают по разному
простветите знающие
может имеет смысл поставить виртуальную машину под виндой и на ней тестить?

Поставишь виртуальную машину, бкдет еще хуже, она тоже ведь ресурсы жрет icon_smile.gif
Поробуй на сервере побаловаться, и ставь в код, чтобы время засекалось, прямо интересно стало, как на Юнихах будет icon_smile.gif

3
 



С нами с 01.10.03
Сообщения: 751
Рейтинг: 318

Ссылка на сообщениеДобавлено: 29/04/06 в 13:29       Ответить с цитатойцитата 

дык я понимаю что будет хуже, но как ни как ближе к реальности, а вообще то конечно лучше сразу на хосте пробовать

Лучший Хостинг для CJ сайтов!

2
 

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 13:41       Ответить с цитатойцитата 

proc3nt писал:
Не пробовал file_get_contents()


Попробовал, действительно повеселее.

Цитата:
$time1 = time();
echo "Вхождений: ";
echo substr_count(file_get_contents('TEMP/test.txt'),"111") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"222") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"333") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"444") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"555") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"666") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"777") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"888") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"999") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"000");
$time2 = time();
echo ". Время выполнения (в секундах): " . ($time2 - $time1);


Первый поиск 13 секунд, последующие 12 секунд. То есть, один поиск для кешированного файла - 1.2 секунды. Меня это вполне устраивает.

Еще бы на 100 000 мелких с такой скоростью работать icon_sad.gif

Если тебе надо просто подрочить, жми сюда

0
 



С нами с 18.01.06
Сообщения: 322
Рейтинг: 487

Ссылка на сообщениеДобавлено: 29/04/06 в 13:49       Ответить с цитатойцитата 

Может вот так попробовать
Код:

$time1 = time();
$file_info = file_get_contents('TEMP/text.txt');
echo "Вхождений: ";
echo substr_count($file_info,"111") . ", ";
echo substr_count($file_info,"222") . ", ";
echo substr_count($file_info,"333") . ", ";
echo substr_count($file_info,"444") . ", ";
echo substr_count($file_info,"555") . ", ";
echo substr_count($file_info,"666") . ", ";
echo substr_count($file_info,"777") . ", ";
echo substr_count($file_info,"888") . ", ";
echo substr_count($file_info,"999") . ", ";
echo substr_count($file_info,"000");
$time2 = time();
echo ". Время выполнения (в секундах): " . ($time2 - $time1);

5
 

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 13:52       Ответить с цитатойцитата 

4 секунды icon_smile.gif

Если тебе надо просто подрочить, жми сюда

0
 



С нами с 18.01.06
Сообщения: 322
Рейтинг: 487

Ссылка на сообщениеДобавлено: 29/04/06 в 13:53       Ответить с цитатойцитата 

icon_smile.gif вот-вот, мы уже ближе к ответу icon_smile.gif

1
 
+ + +


С нами с 26.04.06
Сообщения: 244
Рейтинг: 82

Ссылка на сообщениеДобавлено: 29/04/06 в 14:18       Ответить с цитатойцитата 

При затевании серьезных вещей не стоит искать выход в PHP. Достаточно создать структуры данных и методы ее обработки.

Например если у тебя строки в файле в 200 метров по 200 байт упорядочены по алфавиту, то поиск может занять не более 0,05 сек методом половинного деления. Если же файл нужно изменять, то можно применять его индексацию. Еще можно работать путем бинарного дерева - тогда вобще данные будут в наиболее гибком и быстром виде хранится, но правда усложнятся алгоритмы их обработки.

5
 

Ревнивый муж подобен турку

С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905

Ссылка на сообщениеДобавлено: 29/04/06 в 15:47       Ответить с цитатойцитата 

Sokira писал:
Достаточно создать структуры данных и методы ее обработки.


Угу, согласен. Как раз думаю над структурой данных. Склоняюсь все же сделать 100 000 файлов, плюс индексные файлы по критичным ко времени запросам.

Цитата:
Еще можно работать путем бинарного дерева - тогда вобще данные будут в наиболее гибком и быстром виде хранится, но правда усложнятся алгоритмы их обработки.


Нашел в Гугле, что такое бинарное дерево и другие алгоритмы. Читаю, тихо матерюсь сквозь зубы.

Если тебе надо просто подрочить, жми сюда

0
 



С нами с 05.07.05
Сообщения: 439
Рейтинг: 331

Ссылка на сообщениеДобавлено: 29/04/06 в 17:39       Ответить с цитатойцитата 

Петр Кроликов писал:
Угу, согласен. Как раз думаю над структурой данных. Склоняюсь все же сделать 100 000 файлов, плюс индексные файлы по критичным ко времени запросам.

Нашел в Гугле, что такое бинарное дерево и другие алгоритмы. Читаю, тихо матерюсь сквозь зубы.


насколько помню с лекций, алгоритм бинаритрии не отлчался большой скоростью.

альтруист
FTPCash - Новинка! Рекоммендую.

3
 



С нами с 09.01.05
Сообщения: 11
Рейтинг: 17

Ссылка на сообщениеДобавлено: 30/04/06 в 00:13       Ответить с цитатойцитата 

Петр Кроликов писал:

И там же еще проблема встает. Несколько пользователей могут одновременно писать в один файл. Как сделать так, чтобы они друг другу не мешали, есть готовые рецепты?


http://php.net/manual/ru/function.flock.php

5
 
+ + +


С нами с 26.04.06
Сообщения: 244
Рейтинг: 82

Ссылка на сообщениеДобавлено: 30/04/06 в 00:35       Ответить с цитатойцитата 

Gatos+ писал:
насколько помню с лекций, алгоритм бинаритрии не отлчался большой скоростью.

Это смотря какими руками его писать. В идеале должно получаться log2N поисков, а на практике в лучшем случае log2N + 0.25

Но не стоит забывать, что есть еще B-tree, B+-tree, B*-tree... icon_smile.gif

2
 
Новая тема Новая тема   

Текстовая реклама в форме ответа
Заголовок и до четырех строчек текста
Длина текста до 350 символов
Купить рекламу в этом месте!


Перейти:  



Спонсор раздела Стань спонсором этого раздела!

Реклама на сайте Advertise with us

Опросы

Рецепт новогоднего блюда 2022



Обсудите на форуме обсудить (11)
все опросы »