удаление первой строчки txt

Baranov_Dron

Новичок
удаление первой строчки txt

Но после изучения Си в институте файлы полюбил. ЧТож решил поработать и в php.
Иногда требуется удалить первую строчку файла.
Ну в заготовке была функция, чесно говоря не сам даже писал(не люблю в php с файлами работать - есть БД).
Собственно её код:
PHP:
<?
$file = file( "file.txt" );
array_splice($file,0,1);
$f = fopen("file.txt","w");
   for( $i = 0; $i < count($file); $i++ )
   {  
      fwrite( $f , $words_delit[$i]);  
   }
fclose($f);
?>
Алгоритм её таков, что весь файл заносится в память по сути. Нечего и говорить, что очень ресурсоёмко!
Нужно как то сократить её!
я вижу путь, который я сделал бы в C.
Брал бы по-одному символу и удалял его смещая символы влево, удалял бы циклом по одному символу, пока не дошёл \r\n.
Но выполнить это не могу, считывать то символы не сложно... А вот удалять по-одному представляется проблемой лично для меня.
Чтож 100 бед - один ман!
http://ru2.php.net/manual/ru/ref.filesystem.php
Но тут всего 2-3 функции для записи! и все толком не подходят...
ВОт кое-что поэксперементил...
PHP:
<?
$fp=fopen("1.txt","r+b");
$n=1;
$tmp=false;
   while (false !== ($char = fgetc($fp)))
   {
      echo $n.":";
	     if($char==="\n"){if($tmp) break;}
	     if($char==="\r"){$tmp=true;}
      var_dump($char)."<p>";
      echo "<p>";   $n++;
   }
fseek($fp, 0);
ftruncate($fp,-3);
?>
В общем создалось впечатление, что лучше первоначальное решение. Чтож поделать, что оно ресурсоёмкое...
Может ли кто его опровергнуть?!
 

Alexandre

PHPПенсионер
я вижу путь, который я сделал бы в C.
Брал бы по-одному символу и удалял его смещая символы влево, удалял бы циклом по одному символу, пока не дошёл \r\n.
бред

не надо ничего смещать,
просто пропускаем все, до первого \r\n
а далее читаем и обрабатываем как нам надо.

-~{}~ 17.03.08 19:51:

Baranov_Dron
напиши,
каким видишь правильный алгоритм на Си, а мы поможем его переписать на пхп.
 

StUV

Rotaredom
Алгоритм её таков, что весь файл заносится в память по сути. Нечего и говорить, что очень ресурсоёмко!
ресурсоемкость - понятие "относительное"
какой размер файлов?
в каком режиме они обрабатываются?
скажем, для файлов размером до 5М, изменяемых "по запросу" - я бы не стал так заморачиваться
 

dimagolov

Новичок
у меня вообще стойкое ощущение, что если такая задача возникает, то что-то спроектированно непривильно и текстовый файл совсем не удачное место для хранения данных
 

StUV

Rotaredom
imho, задача "надуманная" - из разряда "как это сделать на пхп?"
в реальной ситуации это ессно проще и правильнее сделать на shell/perl/...
 

Baranov_Dron

Новичок
Вот ща набросал код, суть такова что в оперативке держится не весь файл, а посимвольно.
PHP:
<?
$fpRight=fopen("1.txt","r+b");
$fpRead=fopen("1.txt","r");
   while (false !== ($char = fgetc($fpRead)))
   {
	     if($char==="\n"){break;}
      $n++;
   }
   while (false !== ($char = fgetc($fpRead)))
   {
      fwrite($fpRight , $char);
   }
   $npos=ftell($fpRight);
   ftruncate($fpRight,$npos);
?>
Как идея?! протестил работает! сейчас сделаю удаление любой указанной строчки и ещё протестю на большом каком-нибудь файле, быстрее ли это будет способа в первом посте.

-~{}~ 18.03.08 19:15:

Автор оригинала: Alexandre
бред

не надо ничего смещать,
просто пропускаем все, до первого \r\n
а далее читаем и обрабатываем как нам надо.
Ну это изменить алгоритм поставленной задачи, а не решить её...
Автор оригинала: Alexandre
Baranov_Dron
напиши,
каким видишь правильный алгоритм на Си, а мы поможем его переписать на пхп.
-~{}~ 17.03.08 19:51:
ну я уже плохо его помню) аж в том семестре это было....

-~{}~ 18.03.08 19:15:

Ничего интересного

-~{}~ 18.03.08 19:17:

Автор оригинала: StUV
ресурсоемкость - понятие "относительное"
какой размер файлов?
в каком режиме они обрабатываются?
скажем, для файлов размером до 5М, изменяемых "по запросу" - я бы не стал так заморачиваться
процентов на 99.9% меньше пяти) ну я больше для изучения работы с файлами заморачиваюсь, нежели для практики) а то всю БД да БД...

-~{}~ 18.03.08 19:18:

Автор оригинала: StUV
imho, задача "надуманная" - из разряда "как это сделать на пхп?"
в реальной ситуации это ессно проще и правильнее сделать на shell/perl/...
Ну а если я использую windows? между прочем часто приходится сталкиваться мне с серверами на windows.
 

kode

never knows best
если PHP5, то:

$fin = fopen('in.put','r');
$fout = fopen('out.put','w');

fgets($fin); //вычитаем нашу несчастную первую строчку
stream_copy_to_stream($fin,$fout);

под PHP4 код на 2 строчки больше

while(!feof($fin)){
fwrite($fout,fread($fin));
}

вместо stream_copy_to_stream($fin,$fout);

вот и всё

или для совсем альтернативно одарёных:

PHP:
$fin   = fopen('in.put','r');
$fout = fopen('out.put','w');

fgets($fin); //вычитаем нашу несчастную первую строчку

if(version_compare(phpversion(),'5.0.0')>0){ //PHP5
stream_copy_to_stream($fin,$fout);
}else{ //PHP4
while(!feof($fin)){fwrite($fout,fread($fin));}
}

fclose($fin);
fclose($fout);
 

Baranov_Dron

Новичок
kode спасибо!
stream_copy_to_stream интересная функция!

-~{}~ 18.03.08 19:43:

$fin = fopen('1.txt','r');
$fout = fopen('2.txt','w');

fgets($fin); //вычитаем нашу несчастную первую строчку
stream_copy_to_stream($fin,$fout);
работает когда $fin $fout разные файлы.... конечно можно потом делать удаление и переименование, но всё же сейчас поэксперементирую сейчас со своим кодом)

-~{}~ 18.03.08 20:00:

тест кода
PHP:
<?
$file = file( "file.txt" );
array_splice($file,0,1);
$f = fopen("file.txt","w");
   for( $i = 0; $i < count($file); $i++ )
   {  
      fwrite( $f , $file[$i]);  
   }
fclose($f);
?>
выполнялся 0.383063793182
кода
PHP:
<?
$fpRight=fopen("1.txt","r+b");
$fpRead=fopen("1.txt","r");
   while (false !== ($char = fgetc($fpRead)))
   {
         if($char==="\n"){break;}
      $n++;
   }
   while (false !== ($char = fgetc($fpRead)))
   {
      fwrite($fpRight , $char);
   }
   $npos=ftell($fpRight);
   ftruncate($fpRight,$npos);
?>
19.5792448521
я ожидал разницу раза в 2, но не в 50!
Пожалуй первый способ и был лучше!!! хотя первый способ есть больше оперативки, второй процессора вследствии чего долго выполняется. в теории.
 

Alexandre

PHPПенсионер
второй код,
сперва считаем, потом отрезаем
двойная работа.
 

Baranov_Dron

Новичок
0.0239791870117 рузультат намного лучше!
но это без удаления и переименования, по сути рядом создался такой же файл, но без перовой строки.
Тестировалось на txt файле размером в 1,57 МБ (1 646 749 байт).
Во всех трёх способах один и тот же файл.
OS vista(ток вчера ноут купил, сносить лень)
 

Baranov_Dron

Новичок
Автор оригинала: Alexandre
второй код,
сперва считаем, потом отрезаем
двойная работа.
почему? мы в каждой интерации цикла читаем символ и его записываем, одновремено!

-~{}~ 18.03.08 21:02:

Автор оригинала: Alexandre
переименование - много времени не занимает.
согласен! просто что-то сначало отталкивало, что нужно работать со вторым файлом...
Но пожалуй так и сделаю!
kode ещё раз спасибо!

-~{}~ 13.04.08 18:57:

В общем я боялся работать с 2 файлами, оказалось не напрасно, файл очистился!!!
Хотя по не должен был никак!
По сути работают 2 функции, эта и добавление строчек в конец. Вот строчка удаления первой строчки, которая получилась в конце концов.
public function Get1stWordAndDel()
{
$fin = fopen($this->dir.$this->DirName["file"],'r');
flock($fin,LOCK_EX);
$res=trim(fgets($fin));
if($res)
{
$fout = fopen($this->dir.$this->DirName["tmpfile"],'w');
flock($fout,LOCK_EX);
stream_copy_to_stream($fin,$fout);
fclose($fin);
fclose($fout);
unlink($this->dir.$this->DirName["file"]);
rename($this->dir.$this->DirName["tmpfile"],$this->dir.$this->DirName["file"]);
return $res;
}
else
{
if(feof($fin))
{
$this->error="файл пустой";
fclose($fin);
}
else
{
$this->error="пустая строка";
$fout = fopen($this->dir.$this->DirName["tmpfile"],'w');
flock($fout,LOCK_EX);
stream_copy_to_stream($fin,$fout);
fclose($fin);
fclose($fout);
unlink($this->dir.$this->DirName["file"]);
rename($this->dir.$this->DirName["tmpfile"],$this->dir.$this->DirName["file"]);
}
return false;
}
}

-~{}~ 13.04.08 18:59:

Блиин код уродливо получился((( хотел подправить, но вылезает мессага "Администратор установил, что отредактировать сообщение можно только в течении 1440 минут после его публикации"...
Как понимаю паралельно другой скрипт может вклинится в месте
fclose($fin);
fclose($fout);
unlink($this->dir.$this->DirName["file"]);
rename($this->dir.$this->DirName["tmpfile"],$this->dir.$this->DirName["file"]);
как это избежать?
 
Сверху