Удаление строки из файла

Altex

Новичок
Автор оригинала: lucas
...
PHP:
...
	$file = fopen($file_name,"a+") ;
...
	ftruncate($file,0) ;
	fwrite($file,implode("",$lines)) ;
...
	fclose($file) ;
}
...
Я конечно не "фанат" в PHP, но чем твой код лучше этого:
PHP:
	$file = fopen($file_name,"w") ;
	fwrite($file,implode("",$lines)) ;
	fclose($file) ;
?
 

voodoo

Новичок
Altex, в случае
fopen($file_name,"w"); flock()
файл "зануляется" при открытии (w), до блокировки (flock). как результат -- возможны потери данных.
Хотя, судя по вышеприведенным примерам с file() и потом fopen() это вовсе ни для кого не важно

Вообще, пральна делать так:
fopen(..."r+");
flock
fread()
fseek(0)
fwrite()
ftruncate()
fflush()
flock(UNLOCK)
flose()
Если делать truncate в начале,файловая система может напрягаться не по делу, освобождая и выделяя блоки.

Зы. совет про "implode("",$lines)", вообще говоря, не канает, на больших файлах у ПХП может не хватить памяти все это в "башке" хранить. В этом случае, процедуру seek/read/seek/write повторять блоками
 

Фанат

oncle terrible
Команда форума
если файл большой, то следует задуматься о замене
файла - базой, или пыха - каким-нибудь авком.
 

lucas

Guest
pauk
В массиве вообще-то нумерация с нуля,
а удалив $file[1] мы удаляем не 1-й элемент
А я где-то намекал, что должно быть так?
Hint: передали 0 (первая строка) -- ее и удалили.

all

Спасибо за советы.
Код сейчас переработаем.
 

lucas

Guest
Прошу прощения за задержку.

PHP:
$file_name = "0.dat" ;
$script_name = "index.php" ;
$crlf = "\n" ;

if (isSet($_GET["line"]) == true) 
{	$file = fopen($file_name,"r+") ;
	flock($file,LOCK_EX) ;
	$lines = explode($crlf,fread($file,filesize($file_name))) ;

	if (isSet($lines[(integer) $_GET["line"]]) == true)
	{	unset($lines[(integer) $_GET["line"]]) ;
		fseek($file,0) ;
		$data_size = 0 ;
		ftruncate($file,fwrite($file,implode($crlf,$lines))) ;
		fflush($file) ;
	}

	flock($file,LOCK_UN) ;
	fclose($file) ;
	header("Location: " . $script_name) ;
	exit() ;
}

$file = fopen($file_name,"r") ;
flock($file,LOCK_SH) ;
$lines = explode($crlf,fread($file,filesize($file_name) )) ;
flock($file,LOCK_UN) ;
fclose($file) ;

$count = sizeof($lines) ; for ($a = 0 ; $a < $count ; ++$a) 
{	echo "<p><a href='" . $script_name . "?line=" . $a . "'>" . (strlen(str_replace("\r","",$lines[$a])) == true ? $lines[$a] : "[empty line]") . "</a></p>" ; 
}
Заметки на полях:

1. Может оказаться полезной замена строкой
PHP:
$lines = preg_split("~\r*?\n+\r*?~",fread($file,filesize($file_name))) ;
соответствующей строки из скрипта.

2. В случае необходимости работы с большими файлами (несмотря на то, что PHP для этого не предназначен), полезным окажется блочное чтение/запись. Пример записи:
PHP:
$block_size = 1024 ;

$line = 0 ; $data_size = 0 ; while (sizeof($lines) == true)
{	if (isSet($lines[$line]) == true)
	{	$data_size += fwrite($file,substr($lines[$line],0,$block_size)) ;
		if (strlen($lines[$line]) > $block_size)
		{	$lines[$line] = substr($lines[$line],$block_size) ;
			continue ;
		}
		if (isSet($lines[$line + 1]) == true || $line + 1 == (integer) $_GET["line"])
		{	$data_size += fwrite($file,$crlf) ;
		}
		unset($lines[$line]) ;
	}
	++$line ;
}
 

voodoo

Новичок
про файлы. по основному коду:

между filesize() и fopen() файл может измениться.

после записи и перед flock(LOCK_UN) полезно все-таки сделать fflush(), иначе (возможна ситуация что) буфер будет записан при fclose, т.е. после снятия блокировки, результат -- как обычно, потери данных.

совершенно непонятно зачем второй раз читать файл
 
Сверху