我正在编写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
答案 0 :(得分:20)
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时你可以做的事情更清晰,它不会将整个文件保存在内存中,一次只能保存一行,并且你可以插入它并在任何地方重用该模式,因为它是完整的OO。
答案 1 :(得分:4)
$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 :(得分:4)
这是日志文件的教科书问题,我想提出另一种解决方案。
“在文件开头删除行”方法的问题是,添加新行变得非常慢,一旦它必须删除它所写的每个新行的第一行。
正常的日志文件追加仅涉及在文件系统中的文件末尾写入更多的字节(并且偶尔必须分配一个新扇区,这会导致大量碎片 - 为什么日志文件通常是这样)
但是这里的一个大问题是当你为每一行写入时删除一行中的一行。必须首先将整个文件读入内存然后重写,从而导致硬盘的大量I / O(比较)。更糟糕的是,由于PHP数组的特性,这里的“拆分为PHP数组并跳过第一行”解决方案极其缓慢。如果日志文件大小限制非常小或者写入是未加密的,但是有大量写入(如日志文件的情况),则这不是问题,同样的大量操作必须要进行很多次导致主要的性能缺陷。
这可以想象为停放在50号线上的停车场。停放前50辆车的速度很快,只需在车前方开车并完成。但是当你来到50,并且前面的车(文件的开头)必须被移除你必须驾驶2'车到第1个位置,第3到第2,依此类推,然后才开车进去第50位的最后一辆车。 (并且必须重复每辆你要停车的新车!)
我的建议是保存到不同的日志文件,日期,然后再存储最多30天等。因此利用文件系统,已经完全解决了这个问题。
答案 3 :(得分:2)
您可以使用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);
答案 4 :(得分:0)
典型的操作系统不提供“就地”插入或删除文件内容的功能。您需要做的是编写一个读取第一个文件的函数,并创建一个包含您想要保留的行的
在伪代码中:
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 MB你可能会发现将文件加载到内存中是不可接受的空间使用。
答案 5 :(得分:0)
如果您可以运行linux命令,请尝试split
。它允许您按行数分割以简化操作。
否则,我认为你必须阅读并写入其他2个文件。
答案 6 :(得分:0)
除@Greg's回答之外,您可以将整个文件读入数组,跳过前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);
答案 7 :(得分:0)
这是一个准备好的功能
<?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));
}
}
?>
答案 8 :(得分:0)
以下代码将帮助您删除文件开头的行数
$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);