У меня есть скрипт, который каждый раз вызывается, получает первую строку файла. Известно, что каждая строка имеет точно такую же длину (32 буквенно-цифровых символа) и заканчивается символом «\ r \ n». После получения первой строки сценарий удаляет ее.
Это делается следующим образом:
$contents = file_get_contents($file)); $first_line = substr($contents, 0, 32); file_put_contents($file, substr($contents, 32 + 2)); //+2 because we remove also the \r\n
Очевидно, это работает, но мне было интересно, есть ли более умный (или более эффективный) способ сделать это?
В моем простом решении я в основном читаю и переписываю весь файл только для того, чтобы взять и удалить первую строку .
Нет более эффективного способа сделать это, кроме как переписать файл.
Вчера я придумал эту идею:
function read_and_delete_first_line($filename) { $file = file($filename); $output = $file[0]; unset($file[0]); file_put_contents($filename, $file); return $output; }
сfunction read_and_delete_first_line($filename) { $file = file($filename); $output = $file[0]; unset($file[0]); file_put_contents($filename, $file); return $output; }
Нет необходимости создавать второй временный файл и не помещать весь файл в память:
if ($handle = fopen("file", "c+")) { // open the file in reading and editing mode if (flock($handle, LOCK_EX)) { // lock the file, so no one can read or edit this file while (($line = fgets($handle, 4096)) !== FALSE) { if (!isset($write_position)) { // move the line to previous position, except the first line $write_position = 0; } else { $read_position = ftell($handle); // get actual line fseek($handle, $write_position); // move to previous position fputs($handle, $line); // put actual line in previous position fseek($handle, $read_position); // return to actual position $write_position += strlen($line); // set write position to the next loop } } fflush($handle); // write any pending change to file ftruncate($handle, $write_position); // drop the repeated last line flock($handle, LOCK_UN); // unlock the file } fclose($handle); }
вы можете выполнять итерацию файла, вместо того чтобы помещать их все в память
$handle = fopen("file", "r"); $first = fgets($handle,2048); #get first line. $outfile="temp"; $o = fopen($outfile,"w"); while (!feof($handle)) { $buffer = fgets($handle,2048); fwrite($o,$buffer); } fclose($handle); fclose($o); rename($outfile,$file);
Обычно я бы не рекомендовал открывать оболочку для такого рода вещей, но если вы делаете это нечасто по действительно большим файлам, возможно, что-то нужно сказать:
$lines = `wc -l myfile` - 1; `tail -n $lines myfile > newfile`;
Это просто, и это не связано с чтением всего файла в память.
Я бы не рекомендовал это для небольших файлов, или очень частое использование. Накладные расходы слишком высокие.
Это сдвинет первую строку файла, вам не нужно будет загружать весь файл в память, как вы, используя функцию «файл». Возможно, для небольших файлов это немного медленнее, чем с «файлом» (возможно, но я уверен, что нет), но он может управлять большими файлами без проблем.
$firstline = false; if($handle = fopen($logFile,'c+')){ if(!flock($handle,LOCK_EX)){fclose($handle);} $offset = 0; $len = filesize($logFile); while(($line = fgets($handle,4096)) !== false){ if(!$firstline){$firstline = $line;$offset = strlen($firstline);continue;} $pos = ftell($handle); fseek($handle,$pos-strlen($line)-$offset); fputs($handle,$line); fseek($handle,$pos); } fflush($handle); ftruncate($handle,($len-$offset)); flock($handle,LOCK_UN); fclose($handle); }
Вы можете хранить позиционную информацию в самом файле. Например, первые 8 байтов файла могут хранить целое число. Это целое число является смещением байта первой реальной строки в файле.
Таким образом, вы никогда не удаляете строки. Вместо этого удаление строки означает изменение начальной позиции. fseek (), а затем читать строки как обычно.
В конечном итоге файл станет большим. Вы можете периодически очищать осиротевшие линии, чтобы уменьшить размер файла.
Но серьезно, просто используйте базу данных и не делайте подобных вещей.
Вот один из способов:
$contents = file($file, FILE_IGNORE_NEW_LINES); $first_line = array_shift($contents); file_put_contents($file, implode("\r\n", $contents));
Существует множество других способов сделать это, но все методы будут включать в себя разделение первой строки и сохранение остальных. Вы не можете избежать перезаписи всего файла. Альтернативный вариант:
list($first_line, $contents) = explode("\r\n", file_get_contents($file), 2); file_put_contents($file, implode("\r\n", $contents));
Я думаю, что это лучше всего для любого размера файла
$myfile = fopen("yourfile.txt", "r") or die("Unable to open file!"); $ch=1; while(!feof($myfile)) { $dataline= fgets($myfile) . "<br>"; if($ch == 2){ echo str_replace(' ', ' ', $dataline)."\n"; } $ch = 2; } fclose($myfile);
Вы можете использовать метод file ().
Получает первую строку
$content = file('myfile.txt'); echo $content[0];