Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Интернет » Web-программирование » PHP: Скрипт для удаления одинаковых строк из файла
работает нормально, но когда файл в котором более 80к сток..

Модерирует : Cheery

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2

Открыть новую тему     Написать ответ в эту тему

Brodyaga



Silver Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Cheery
Ну так я же с разрезанием файла сделал
Просто я попробовал простым способом построчного чтения обработать 4 ГБ файл, и у меня не хватило времени(стандартных 30 секунд на хостах), и всвязи с этим прерыванием повредился и исходный и новый файл.
DJCosmos

Код:
 
<?php
ini_set("memory_limit","0M");
$num_parts=20;
$filename="new.txt";
$fsize=filesize($filename);
$part=ceil($fsize/$num_parts);
$sum=0;
for($i=0;$i<=$num_parts-1;$i++){
$parts[$i]=$part;
$sum+=$part;
}
$lastpart=$fsize-($sum-$part);
$parts[$num_parts-1]=$lastpart;
$fpm=fopen($filename,"r");
$fpa=fopen("$filename.tmp","w");
foreach($parts as $k=>$v){
$from=array_sum(array_slice($parts,0,$k));
$to=$from+$v;
fseek($fpm,$from);
$fp=fopen("$filename$k","w");
fwrite($fp,fread($fpm,$v));
fwrite($fpa,join("",array_diff(array_unique(file("$filename$k")),array("\n"))));
fclose($fp);
unlink("$filename$k");
}
fclose($fpa);
$fpa=fopen("$filename.new","w");
fwrite($fpa,join("",array_diff(array_unique(file("$filename.tmp")),array("\n"))));
fclose($fpa);
unlink($filename.".tmp");
?>
 

Ну можно вот так
---
Есть у меня мысль вообще посимвольного чтения, как додумаю-выложу код.


----------
Damn Metal

Всего записей: 2713 | Зарегистр. 07-01-2006 | Отправлено: 19:46 11-09-2006
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
вот..  

Код:
<?php
  $fw=fopen('out.txt','w');
  $fr=fopen('test.txt','r');
  $fs=filesize('test.txt');
  while (!feof($fr))  
   {
    $str = fgets($fr, 4096);
    $curpos=ftell($fr);
    if ($curpos==$fs) break;
    if (check_string($str,$fr)) {fseek($fr,$curpos);continue;}
      else {fseek($fr,$curpos);fwrite($fw,$str);}    
   }
   fclose($fr);
   fclose($fw);
function check_string($str,$fp)
{
  while (!feof($fp))  
   {
    $strf = fgets($fp, 4096);
    if ($strf==$str) return true;    
   }
  return false;
}
?>

исходный не должен портиться.
да, этот алгоритм занимает много времени, но не ест памяти.

----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 19:49 11-09-2006 | Исправлено: Cheery, 19:50 11-09-2006
Brodyaga



Silver Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Cheery и так идет борьба-память или время

Код:
 
<?php
$filename="new.txt";
$defpartsize=500000;
$fsize=filesize($filename);
if($fsize<=$defpartsize){
$num_parts=20;
}
else{
$num_parts=ceil($fsize/$defpartsize);
}
$part=ceil($fsize/$num_parts);
$sum=0;
for($i=0;$i<=$num_parts-1;$i++){
$parts[$i]=$part;
$sum+=$part;
}
$lastpart=$fsize-($sum-$part);
$parts[$num_parts-1]=$lastpart;
$fpm=fopen($filename,"r");
$fpa=fopen("$filename.tmp","w");
foreach($parts as $k=>$v){
$from=array_sum(array_slice($parts,0,$k));
$to=$from+$v;
fseek($fpm,$from);
$fp=fopen("$filename$k","w");
fwrite($fp,fread($fpm,$v));
fwrite($fpa,join("",array_diff(array_unique(file("$filename$k")),array("\n"))));
fclose($fp);
unlink("$filename$k");
}
fclose($fpa);
$fpa=fopen("$filename.new","w");
fwrite($fpa,join("",array_diff(array_unique(file("$filename.tmp")),array("\n"))));
fclose($fpa);
unlink($filename.".tmp");
?>
 

А вот ещё вариация-можно явно указать, на какие части резать.Кстати, получилось быстрее!
Я указал 500000 и скорость ощутимо увеличилась, я даже сам не ожидал.
 
Добавлено:
Ставим 100000 и наслаждаемся работой скрипта.Кто-нибудь, потестите с жестким ограничением памяти, у меня не получается перегрузить ЦП

----------
Damn Metal

Всего записей: 2713 | Зарегистр. 07-01-2006 | Отправлено: 20:14 11-09-2006
DJCosmos



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Brodyaga
А почему в результирующем файле начиная со второй строчки значения начиниются с пробела?
 
Cheery
Запускаю твой скрипт у себя, мне выдаёт:
Fatal error: Maximum execution time of 30 seconds exceeded in ........

Всего записей: 55 | Зарегистр. 12-06-2004 | Отправлено: 20:42 11-09-2006 | Исправлено: DJCosmos, 20:46 11-09-2006
Brodyaga



Silver Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
хм...
Интересный феномен, у меня такого нет...
а на какой машине тестируем?

Код:
 
<?php
$filename="new.txt";
$defpartsize=100000;
$fsize=filesize($filename);
if($fsize<=$defpartsize){
$num_parts=20;
}
else{
$num_parts=ceil($fsize/$defpartsize);
}
$part=ceil($fsize/$num_parts);
$sum=0;
for($i=0;$i<=$num_parts-1;$i++){
$parts[$i]=$part;
$sum+=$part;
}
$lastpart=$fsize-($sum-$part);
$parts[$num_parts-1]=$lastpart;
$fpm=fopen($filename,"r");
$fpa=fopen("$filename.tmp","w");
foreach($parts as $k=>$v){
$from=array_sum(array_slice($parts,0,$k));
$to=$from+$v;
fseek($fpm,$from);
$fp=fopen("$filename$k","w");
fwrite($fp,fread($fpm,$v));
fwrite($fpa,trim(join("",array_diff(array_unique(file("$filename$k")),array("\n")))));
fclose($fp);
unlink("$filename$k");
}
fclose($fpa);
$fpa=fopen("$filename.new","w");
fwrite($fpa,trim(join("",array_diff(array_unique(file("$filename.tmp")),array("\n")))));
fclose($fpa);
unlink($filename.".tmp");
?>
 

Если нет возможности копаться, лучше решить в лоб...

----------
Damn Metal

Всего записей: 2713 | Зарегистр. 07-01-2006 | Отправлено: 20:51 11-09-2006
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
DJCosmos

Цитата:
Запускаю твой скрипт у себя, мне выдаёт:

я же говорю.. на работу моего требуется время.
попробуй поставить в начале set_time_limit(600)
но в safe_mode это ни к чему не приведет.


----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 20:52 11-09-2006
Brodyaga



Silver Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Гм, хотя это не решение...надо думать, не хочется ещё один цикл для массива строк создавать..


----------
Damn Metal

Всего записей: 2713 | Зарегистр. 07-01-2006 | Отправлено: 20:54 11-09-2006
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Вот "ускоренный" вариант.. пишешь в $numstr со скольки строками одновременно работать

Код:
<?php
  $numstr=5;  
  $fw=fopen('out.txt','w');
  $fr=fopen('test.txt','r');
  $fs=filesize('test.txt');
  while (!feof($fr))  
   {
   $count=1;
   $arr=array();
    while($count<=$numstr && !feof($fr))
     {    
      $str = fgets($fr, 4096);
      if (in_array($str,$arr)) continue;
      $arr[]=$str;
      $count++;
     }
     $curpos=ftell($fr);
     if ($arr[0]=='') break;
     if (($temp=check_string($arr,$fr))===true) {fseek($fr,$curpos);continue;}
       else {fseek($fr,$curpos);fwrite($fw,join('',$temp));}    
   }
   fclose($fr);
   fclose($fw);
function check_string($str,$fp)
{
  global $numstr;
  while (!feof($fp))  
  {
  $count=1;
  $arr=array();
  while ($count<=$numstr && !feof($fp))  
      {
      $tmp = fgets($fp, 4096);
      if (in_array($tmp,$arr)) continue;
      $arr[]=$tmp;
      $count++;
      }
  $str=array_diff($str,$arr);
  if (empty($str)) return true;
  }
  return $str;
}
?>

но все равно.. ворочать такие вещи на сервере означает что то изначально неправильное.

----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 22:24 11-09-2006 | Исправлено: Cheery, 22:25 11-09-2006
N Sensey N



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Может все таки имеет смысл заюзать мускул?

----------
sPaiz-Nuke - Free PHP CMS Web Design and Development Портал для израильтян

Всего записей: 1409 | Зарегистр. 01-10-2002 | Отправлено: 08:41 12-09-2006
druzhanja2

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
у меня есть файл txt с 20 000 000 фраз. Надо из них выбрать строки у которых есть слово text. Как это сделать?
 
И еще как сделать так что бы были уникальные строки, т.е.  
 
например есть такой фрагмент файлика:
 
одноклассники.ru моя страница
inmarket.biz
одноклассники
 
надо что бы из этого получилось:
 
одноклассники.ru моя страница
inmarket.biz
 
т.е. "одноклассники" надо удалить т.к. есть "одноклассники.ru моя страница"

Всего записей: 1 | Зарегистр. 15-04-2011 | Отправлено: 14:17 15-04-2011
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
druzhanja2

Цитата:
Надо из них выбрать строки у которых есть слово text. Как это сделать?  

читаете построчно и с помощью регулярного выражения проверяете есть ли слово..
но быстрее всего будет использовать системные команды - если Linux на сервере, то с помощью grep

Цитата:
И еще как сделать так что бы были уникальные строки, т.е.

а какие критерии? ну есть "одноклассники" и? а если одинаковое слово "страница", то как быть?

----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 20:26 15-04-2011
moj53

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Доброго времени суток! Как решить задачку: есть примерный текст                                                             СТРОКА 1.....................
СТРОКА 1.............
СТРОКА 3...................
СТРОКА 3............        ,т.е дубликаты строк с одинаковым началом, но разным количесвом символов ! Надо как-то удалить дубликат строки с меньшим количесвом символов?????? Спасибо.                                                                                

Всего записей: 11 | Зарегистр. 17-09-2011 | Отправлено: 12:56 28-10-2011
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
moj53
символы - это точки или что?  
критерий какой? насколько должно быть "одинаковое" начало?

----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 20:47 28-10-2011
moj53

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Текст- это словарная статья, типа                                                                                                                                                             ГОМЕОВОКС (HOMEOVOX)    Лаборатория БУАРОН код ATX: Владелец регистрационного удостоверения:  
ГОМЕОВОКС® (HOMEOVOX)код ATX: Владелец регистрационного удостоверения: Laboratoires BOIRON
ХОНДРОФЕН (HONDROFEN)    код ATX: Владелец регистрационного удостоверения: БИОСИНТЕЗ, ОАО
ХОНДРОФЕН (HONDROFEN)    код ATX: Владелец регистрационного                    т.е текст из 15000 препаратов, но есть дубликаты, мне надо удалить дубликат с меньшим количеством символов, чтобы не засорять статью                                                                                                                                                                                      

Всего записей: 11 | Зарегистр. 17-09-2011 | Отправлено: 22:33 28-10-2011
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
moj53
тут есть свои сложности.. нужен четкий критерий, потому что, к примеру

Цитата:
ГОМЕОВОКС (HOMEOVOX)

и

Цитата:
ГОМЕОВОКС® (HOMEOVOX)

различная запись. как определить, что это одно лекарство,  а не, скажем, модификация?
на словах то легко сказать, но программные языки не обладают "разумностью" )

----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 22:58 28-10-2011
moj53

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
повторяющиеся препараты будут иметь одинаковое начало и значения типа ® я сам отредактирую. текст типа " ХОНДРОФЕН (HONDROFEN)  " разное количество  буков....и знаков препинания"                       ХОНДРОФЕН (HONDROFEN)  " разное количество  буков....и знаков препинания"                                    ХОНДРОФЕН (HONDROFEN)  " разное количество  буков....и знаков препинания"                                   ГОМЕОВОКС (HOMEOVOX)   " разное количество  буков....и знаков препинания"                                      ГОМЕОВОКС (HOMEOVOX)   " разное количество  буков....и знаков препинания"         и так около 15000 наименований разных препаратов, начало типа ПРЕПАРАТпробел(ПРЕПАРАТ)пробелТЕКСТ

Всего записей: 11 | Зарегистр. 17-09-2011 | Отправлено: 10:34 29-10-2011
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ок, пусть типичная строка будет

Цитата:
ГОМЕОВОКС (HOMEOVOX)   " разное количество  буков....и знаков препинания"      

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

Код:
<?php
$str=<<<DAT
ХОНДРОФЕН (HONDROFEN)  " разное количество  буков....и знаков препинания"                                    
ХОНДРОФЕН (HONDROFEN)  " разное количество  буков....и знаков препинания+++"                                    
ГОМЕОВОКС (HOMEOVOX)   " разное количество  буков....и знаков препинания"                                      
ГОМЕОВОКС (HOMEOVOX)   " разное количество  буков....и знаков препинания+++"    
DAT;
$data = array();
preg_match_all('/^(.*\))(.*)$/mU', $str, $matches);
if(is_array($matches[1]))
{
 foreach($matches[1] as $index=>$drug)
 {
   $description = trim($matches[2][$index]);
   if(!isset($data[$drug]) || strlen($description)>strlen($data[$drug])) $data[$drug] = $description;
 }
 
 $fp = fopen('data.txt', 'w') or die('Unable to create file');
 foreach($data as $name=>$description)
    fwrite($fp, $name . $description . "\n");
 fclose($fp);
}
?>


----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 04:42 30-10-2011
moj53

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Спасибо!!!

Всего записей: 11 | Зарегистр. 17-09-2011 | Отправлено: 14:22 30-10-2011
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2

Компьютерный форум Ru.Board » Интернет » Web-программирование » PHP: Скрипт для удаления одинаковых строк из файла


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2025

LiteCoin: LgY72v35StJhV2xbt8CpxbQ9gFY6jwZ67r

Рейтинг.ru