Как использовать PHP, чтобы удалить X количество строк в начале текстового файла? - PullRequest
6 голосов
/ 19 октября 2008

Я пишу скрипт PHP, и скрипт выводит простой текстовый файл журнала операций, которые он выполняет. Как бы я использовал PHP, чтобы удалить первые несколько строк из этого файла, когда он достигнет определенного размера файла?

В идеале мне бы хотелось, чтобы первые две строки (созданная дата / время были пустыми) и началось удаление со строки 3 и удаление количества строк X Я уже знаю о функции filesize(), поэтому буду использовать ее для проверки размера файла.

Пример текста журнала:

*** LOG FILE CREATED ON 2008-10-18 AT 03:06:29 ***

2008-10-18 @ 03:06:29  CREATED: gallery/thumbs
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_9423.JPG to gallery/IMG_9423.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_9188.JPG to gallery/IMG_9188.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_9236.JPG to gallery/IMG_9236.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_9228.JPG to gallery/IMG_9228.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_3104.JPG to gallery/IMG_3104.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/First dance02.JPG to gallery/First dance02.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/BandG02.JPG to gallery/BandG02.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/official03.JPG to gallery/official03.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/Wedding32.JPG to gallery/Wedding32.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/Gettaway car16.JPG to gallery/Gettaway car16.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/Afterparty05.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/IMG_9254.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/IMG_9175.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/official05.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/First dance01.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/Wedding29.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/men walking.jpg

Ответы [ 9 ]

20 голосов
/ 19 октября 2008

Используйте SPL, Люк

PHP 5 поставляется с большим количеством итераторов:

<?php

$line_to_strip = 5;
$new_file = new SplFileObject('test2.log', 'w');

foreach (new LimitIterator(new SplFileObject('test.log'), $line_to_strip) as $line)
    $new_file->fwrite($line);    

?>

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

4 голосов
/ 20 октября 2008

Это проблема учебников из файлов журналов, и я хотел бы предложить другое решение.

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

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

Но большая проблема здесь в том, что вы удаляете строку в начале для каждой записанной строки. Весь файл сначала должен быть считан в память, а затем переписан, что приводит к огромному количеству операций ввода-вывода на жесткий диск (для сравнения). Что еще хуже, решения «разбить на массив PHP и пропустить первые строки» здесь крайне медленные из-за природы массивов PHP. Это не проблема, если ограничение размера файла журнала очень мало или если оно записано не часто, но при большом количестве записей (как в случае с файлами журналов) одну и ту же огромную операцию необходимо выполнять много раз. что приводит к основным недостаткам производительности.

Это можно представить как парковку автомобилей на линии с местом для 50 человек. Парковка первых 50 автомобилей - это быстро, просто въезжайте за машиной впереди и все готово. Но когда вы приближаетесь к 50, и автомобиль в передней части (начало файла) должен быть удален, вы должны довести 2-ую машину до 1-й позиции, с 3 по 2 и так далее, прежде чем вы сможете въехать с последняя машина на 50-й позиции. (И это должно быть повторено для каждой новой машины, которую вы хотите оставить!)

Вместо этого я предлагаю сохранить в разных лог-файлах по дате, а затем сохранить максимум 30 дней назад и т. Д. Таким образом, мы используем файловую систему, которая уже отлично справилась с этой проблемой.

4 голосов
/ 19 октября 2008
$x_amount_of_lines = 30;
$log = 'path/to/log.txt';
if (filesize($log) >= $max_size)) {
  $file = file($log);
  $line = $file[0];
  $file = array_splice($file, 2, $x_amount_of_lines);
  $file = array_splice($file, 0, 0, array($line, "\n")); // put the first line back in
  ...
}

редактировать: с исправлением от rcar и сохранением первой строки.

2 голосов
/ 19 октября 2008

Вы можете использовать функцию file () для чтения файла в массив строк, а затем использовать array_slice () для удаления первых X строк.

$X = 100; // Number of lines to remove

$lines = file('log.txt');
$first_line = $lines[0];
$lines = array_slice($lines, $X + 2);
$lines = array_merge(array($first_line, "\n"), $lines);

// Write to file
$file = fopen('log.txt', 'w');
fwrite($file, implode('', $lines));
fclose($file);
0 голосов
/ 27 декабря 2017

следующий код поможет вам удалить количество строк в начале файла

$content = file('file.txt');
array_splice($content, 0, 5); // this line will delete first 5 lines //change asper your requirement  
file_put_contents('file.txt', $content);
0 голосов
/ 13 июля 2017

Вот функция готовности к работе

<?php
//--------------------------------
// FUNCTION TO TRUNCATE LOG FILES
//--------------------------------
function trim_log_to_length($path,$numHeaderRows,$numRowsToKeep){
    $file = file($path);
    $headerRows = array_slice($file,0,$numHeaderRows);
    // if this file is long enough were we should be truncating it
    if(count($file) - $numRowsToKeep > $numHeaderRows){
        // figure out the rows we wanna keep
        $dataRowsToKeep = array_slice($file,count($file)-$numRowsToKeep,$numRowsToKeep);
        // write the file
        $newFileRows = array_merge($headerRows,$dataRowsToKeep);
        file_put_contents($path, implode($newFileRows));
    }
}
?>
0 голосов
/ 19 октября 2008

В качестве альтернативы @ ответа Грега вы можете прочитать весь файл в массив, пропустить первые X записей, а затем переписать массив в файл.

Как подход: http://us3.php.net/manual/en/function.file-get-contents.php

$fle = file_get_contents("filename");
// skip X many newlines, overwriting the contents of the string with ""
// http://us3.php.net/manual/en/function.file-put-contents.php
file_put_contents("filename", $fle);
0 голосов
/ 19 октября 2008

Если вы можете запустить команду linux, попробуйте split. Это позволяет вам делиться на количество строк, чтобы упростить процесс.

В противном случае, я думаю, вам придется прочитать его и записать в 2 других файла.

0 голосов
/ 19 октября 2008

Типичные операционные системы не предоставляют возможность вставлять или удалять содержимое файла «на месте». Вам нужно написать функцию, которая читает первый файл и создает новый выходной файл, содержащий строки, которые вы хотите сохранить. Затем, когда вы закончите, удалите старый файл и переименуйте новый в старое имя.

В псевдокоде:

open original file IN for reading
create new output file OUT
read the first two lines from IN
write these lines to OUT
for each line to skip:
    read a line from IN
for the remainder of the file:
    read a line from IN
    write the line to OUT
close IN
close OUT
delete IN
rename OUT to IN

Преимущество этого метода перед некоторыми другими представленными в том, что не требует, чтобы вы сначала считали весь файл в память. Вы не упомянули, насколько велик ваш верхний предел размера, но если это что-то около 100 МБ, вы можете обнаружить, что загрузка файла в память недопустима.

...