我猜测是fgets函数,但我找不到具体的语法。我正在尝试读取日志文件中最后添加的行(我认为用字符串更容易)。
最简单的朴素解决方案是:
$file = "/path/to/file";
$data = file($file);
$line = $data[count($data)-1];
虽然这样会将整个文件加载到内存中,可能会有问题(也可能没有)。更好的解决方法是:
$file = escapeshellarg($file); // for the security concious (should be everyone!)
$line = `tail -n 1 $file`;
看起来这就是你想要的:
tekkie.flashbit.net: PHP中的Tail功能
它实现了一个函数,使用负索引的fseek()从文件末尾向上滚动文件。您可以定义要返回多少行。
代码也可在GitHub的Gist中获得:
// full path to text file
define("TEXT_FILE", "/home/www/default-error.log");
// number of lines to read from the end of file
define("LINES_COUNT", 10);
function read_file($file, $lines) {
//global $fsize;
$handle = fopen($file, "r");
$linecounter = $lines;
$pos = -2;
$beginning = false;
$text = array();
while ($linecounter > 0) {
$t = " ";
while ($t != "\n") {
if(fseek($handle, $pos, SEEK_END) == -1) {
$beginning = true;
break;
}
$t = fgetc($handle);
$pos --;
}
$linecounter --;
if ($beginning) {
rewind($handle);
}
$text[$lines-$linecounter-1] = fgets($handle);
if ($beginning) break;
}
fclose ($handle);
return array_reverse($text);
}
$fsize = round(filesize(TEXT_FILE)/1024/1024,2);
echo "<strong>".TEXT_FILE."</strong>\n\n";
echo "File size is {$fsize} megabytes\n\n";
echo "Last ".LINES_COUNT." lines of the file:\n\n";
$lines = read_file(TEXT_FILE, LINES_COUNT);
foreach ($lines as $line) {
echo $line;
}
tail
确实导致瓶颈,而不是对大型数据库进行操作,我仍然不愿意使用它。 - Matthew Scharleytail
命令,例如非UNIX或某些共享主机,则以下代码非常有用;-) 由于php代码有效地使用fseek
仅读取文件尾部,因此性能差异必须很小。 - PaulHdefine('YOUR_EOL', "\n");
$fp = fopen('yourfile.txt', 'r');
$pos = -1; $line = ''; $c = '';
do {
$line = $c . $line;
fseek($fp, $pos--, SEEK_END);
$c = fgetc($fp);
} while ($c != YOUR_EOL);
echo $line;
fclose($fp);
这样做更好,因为它不会将整个文件加载到内存中...
如果您使用与脚本所在操作系统的默认行尾相同的行尾,则将YOUR_EOL设置为正确的行尾。您可以使用常量PHP_EOL。
function seekLastLine($f) {
$pos = -2;
do {
fseek($f, $pos--, SEEK_END);
$ch = fgetc($f);
} while ($ch != "\n");
}
-2
的原因是最后一个字符可能是\n
要获取最后一行,你可以逐行读取文件并保存最后读取的那一行。
如果你在使用Unix/Linux系统,也可以考虑使用shell命令tail。
tail -n 1 filename
file
函数可以逐行读取文件内容,并将每一行作为数组的一个元素返回。$lines = file('log.txt');
$lastLine = array_pop($lines);
为什么只读最后一行?
function readLines($fp, $num) {
$line_count = 0; $line = ''; $pos = -1; $lines = array(); $c = '';
while($line_count < $num) {
$line = $c . $line;
fseek($fp, $pos--, SEEK_END);
$c = fgetc($fp);
if($c == "\n") { $line_count++; $lines[] = $line; $line = ''; $c = ''; }
}
return $lines;
}
$filename = "content.txt";
$fp = @fopen($filename, "r");
print_r(readLines($fp, 2));
fclose($fp);
@unique_stephen,你的答案有缺陷。PHP fseek 成功返回 0,失败返回 -1。将结果存储在 $begining 中,然后稍后在 ftell() 的过滤器中使用它是不正确的。如果我的声望更高,我会投票否决并留下评论。这是 unique_stephen 函数的修改版本。
function readlastline($fileName)
{
$fp = @fopen($fileName, "r");
if (fseek($fp, 0) == -1)
exit('Cannot seek to beginning of the file');
$pos = -1;
$t = " ";
while ($t != "\n") {
if (fseek($fp, $pos, SEEK_END) == -1)
exit('Cannot seek to the end of the file');
if (ftell($fp) == 0) {
break;
}
$t = fgetc($fp);
$pos = $pos - 1;
}
$t = fgets($fp);
fclose($fp);
return $t;
}
注意:PHP的fseek无法管理大于PHP_MAX_INT(32位有符号数字,即使在64位二进制文件上也是如此)的文件末尾。
function readlastline($fileName)
{
$fp = @fopen($fileName, "r");
$begining = fseek($fp, 0);
$pos = -1;
$t = " ";
while ($t != "\n") {
fseek($fp, $pos, SEEK_END);
if(ftell($fp) == $begining){
break;
}
$t = fgetc($fp);
$pos = $pos - 1;
}
$t = fgets($fp);
fclose($fp);
return $t;
}
function readlastline($fileName)
{
$fp = @fopen($fileName, "r");
$begining = fseek($fp, 0);
$pos = -1;
$t = " ";
while ($t != "\n") {
fseek($fp, $pos, SEEK_END);
if(ftell($fp) == $begining){
break;
}
$t = fgetc($fp);
$pos = $pos - 1;
}
$t = fgets($fp);
fclose($fp);
return $t;
}
escapeshellarg
的示例中包含其余所需的代码,那就太好了。创建一个字符串并不能神奇地获取任何内容的最后一行。 - cartertail
命令实现的。很遗憾,生活中没有什么是魔法。 - Matthew Scharley