Удаление дубликатов в больших файлах, проблема...

jeka!

Просто Member
Удаление дубликатов в больших файлах, проблема...

Написал скрипт который открывает файл и удаляет все дублирующиеся записи, потом сохраняет его под новым именем.
На локалке всё прекрасно работает, файлы размером 6 мегов нормально обрабатываются, поставил скрипт на хостинг sweb.ru и там нифига он не работает.
В общем файлы до 1 мега обрабатываются, всё что больше, нет, скрипт умерает и браузер пишет "500 ошибку".

Файлы имеют такой вид:
127.0.0.1
127.0.0.2
127.0.0.3
127.0.0.4
и т.д.

Скрипт:
PHP:
if (file_exists('ip.txt')) {
	$fp=fopen('ip.txt','r');
	$fr=fread($fp,filesize('ip.txt'));
	fclose($fp);
	$arr=explode('\n',$fr);
	foreach ($arr as $val) {
		if ($val=="" || $val=='\n') continue;
		$val=str_replace('\n','',$val);
		$new[$val]=null;
	}
	$fp=fopen('ipnew.txt','w');
	foreach ($new as $key => $val) {
		fputs($fp,$key.'\n');
	}
	fclose($fp);
}
Помогите решить проблему средствами PHP.
Или если не возможно, тогда может есть какая нибудь линуксовая команда, которая удаляет дубликаты из файлов.
 

Toshik

Guest
Может быть рациональнее будет сделать что бы при добавлении нового IP была проверка на возможное существования такого IP в файле!?
 

Lav

Guest
Если скрипт дохнет сразу, возможно, он упирается в лимит по используемой памяти. Попробуй обрабатывать файл по частям.

Если скрипт зависает и долго не отвечает, возможно, он упирается в лимит по времени исполнения. Попробуй поиграться с функцией set_time_limit().
 

Demiurg

Guest
твой скрипт пишется в 3 строчки
[m]file[/m] + [m]array_unique[/m]
но ограничение памяти, действительно может сосздавать проблемы.
 

гоша

Guest
while(!feof($fpIn))
{
$s=fgets($fpIn)
if(!isset($keys[$s])) fwrite($fpOut,$s)
$keys[$s]=1;
}

man uniq
 

Demiurg

Guest
>Через БД все было бы гораздо проще
а если подумать ? или попробовать потестировать ?
 

jeka!

Просто Member
Может быть рациональнее будет сделать что бы при добавлении нового IP была проверка на возможное существования такого IP в файле!?
Это делать не рационально в плане используемых ресурсов компа.
Если скрипт дохнет сразу, возможно, он упирается в лимит по используемой памяти. Попробуй обрабатывать файл по частям.
Он я думаю именно в это и упирается.
твой скрипт пишется в 3 строчки
file + array_unique
но ограничение памяти, действительно может сосздавать проблемы.
Да, так конечно можно, но с файлами до 5 мегов (точно не помню).
Дело в том, что file() вобще не работает с файлами большего размера, и тут хоть 500 мегов лимит памяти выставляй, толку никакого. Я эту тему на форуме подымал ещё год назад.
А у меня списки проксей могут быть и по 20 метров.

while(!feof($fpIn))
{
$s=fgets($fpIn)
if(!isset($keys[$s])) fwrite($fpOut,$s)
$keys[$s]=1;
}
Практически тоже самое, только скрипт умрёт не сразу, а немного позднее когда переменная $keys[$s] заполнится до лимита памяти.
Хотя с другой стороны, если её размер проверять, и освобождать если заполнится, то возможно так можно и сделать, или в 2 этапа пройти сортировку.
Хотя наверное мала вероятность в данной ситуации, что стока наберётся оригиналов.
Надо в общем потестировать...
Через БД все было бы гораздо проще
Ну вобще то я так на край и хотел делать, просто создать временную таблицу, записать туда построчно в униальную колонку все строки и потом выбрать соответственно.
Но это не пхп решение...

Меня просто удивляет такой факт, у меня на локалке стоит denver с настройками по умолчанию, я свободно читаю файлы размером в 700 мегов, тобишь выводил сумму MD5 для всоего архива фильмов.
А на хостинге даже 5 меговые файлы не загружаются, от чего это зависит, не понятно...
 

Lav

Guest
Задача решается сортировкой исходного файла. После этого нахождение дубликатов превращается в элементарную задачу. Загрузку памяти можно сократить до десятков байт.

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

P. S. Google нашёл более простое решение. :)

http://www.die.net/doc/linux/man/man1/sort.1.html

Там есть такой параметр, называется "q". Вроде бы, должен отфильтровывать повторяющиеся строки. Так что вопрос лишь в запуске команды через shell_exec.
 

Demiurg

Guest
Lav
тогда почему бы у себя на машине сразу и не убить дубликаты ?

-~{}~ 30.03.04 10:42:

только что попробовал прочитать файл 26М, все нормально.
php4.3.4 apache 1.3.29
 

Lav

Guest
Demiurg
А это, кстати, вполне может оказаться самым простым решением. Но в начальной постановке задачи были слова "средствами PHP" и "линуксовая команда", так что приходится выкручиваться. ;-)
 

jeka!

Просто Member
Спасибо за man sort, http://www.die.net/doc/linux/man/man1/sort.1.html
думаю теперь разберусь...
Понятное дело что если отсортировать, то всё проще будет, тогда можно просто файлы на край поделить, скажем по 1 мегу и рекурсивно обработать..
 

Nime

Guest
Originally posted by jeka!
Спасибо за man sort, http://www.die.net/doc/linux/man/man1/sort.1.html
думаю теперь разберусь...
Понятное дело что если отсортировать, то всё проще будет, тогда можно просто файлы на край поделить, скажем по 1 мегу и рекурсивно обработать..
jeka, смотри ключ "-u"
 

jeka!

Просто Member
Да, всё сделал, получилось коротко и быстро...
sort --ignore-leading-blanks --unique --output=./sort.ip.txt ./ip.txt
 
Сверху