类似于:How to read only 5 last line of the text file in PHP?
我有一个大型日志文件,我希望能够在文件中显示位置X的100行。
我需要使用fseek
而不是file()
,因为日志文件太大了。
我有类似的功能但它只会从文件的末尾读取。如何修改以便也可以指定起始位置?我还需要从文件的末尾开始。
function read_line($filename, $lines, $revers = false)
{
$offset = -1;
$i = 0;
$fp = @fopen($filename, "r");
while( $lines && fseek($fp, $offset, SEEK_END) >= 0 ) {
$c = fgetc($fp);
if($c == "\n" || $c == "\r"){
$lines--;
if($revers){
$read[$i] = strrev($read[$i]);
$i++;
}
}
if($revers) $read[$i] .= $c;
else $read .= $c;
$offset--;
}
fclose ($fp);
if($revers){
if($read[$i] == "\n" || $read[$i] == "\r")
array_pop($read);
else $read[$i] = strrev($read[$i]);
return implode('',$read);
}
return strrev(rtrim($read,"\n\r"));
}
我要做的是创建一个基于Web的日志查看器,它将从文件末尾开始并显示100行,当按下“下一步”按钮时,将显示其前面的下一行。
答案 0 :(得分:3)
如果您使用的是Unix,则可以使用sed
工具。例如:从文件中获取第10-20行:
sed -n 10,20p errors.log
您可以在脚本中执行此操作:
<?php
$page = 1;
$limit = 100;
$off = ($page * $limit) - ($limit - 1);
exec("sed -n $off,".($limit+$off-1)."p errors.log", $out);
print_r($out);
这些行在$out
数组中可用。
答案 1 :(得分:3)
这使用fseek
从指定的偏移量开始读取100行文件。如果偏移量大于日志中的行数,则读取前100行。
在您的应用程序中,您可以通过 prev 和 next 的查询字符串传递当前偏移量,并将下一个偏移量作为基础。您还可以存储并传递当前文件位置以提高效率。
<?php
$GLOBALS["interval"] = 100;
read_log();
function read_log()
{
$fp = fopen("log", "r");
$offset = determine_offset();
$interval = $GLOBALS["interval"];
if (seek_to_offset($fp, $offset) != -1)
{
show_next_button($offset, $interval);
}
$lines = array();
for ($ii = 0; $ii < $interval; $ii++)
{
$lines[] = trim(fgets($fp));
}
echo "<pre>";
print_r(array_reverse($lines));
}
// Get the offset from the query string or default to the interval
function determine_offset()
{
$interval = $GLOBALS["interval"];
if (isset($_GET["offset"]))
{
return intval($_GET["offset"]) + $interval;
}
return $interval;
}
function show_next_button($offset, $interval)
{
$next_offset = $offset + $interval;
echo "<a href=\"?offset=" . $offset . "\">Next</a>";
}
// Seek to the end of the file, then seek backward $offset lines
function seek_to_offset($fp, $offset)
{
fseek($fp, 0, SEEK_END);
for ($ii = 0; $ii < $offset; $ii++)
{
if (seek_to_previous_line($fp) == -1)
{
rewind($fp);
return -1;
}
}
}
// Seek backward by char until line break
function seek_to_previous_line($fp)
{
fseek($fp, -2, SEEK_CUR);
while (fgetc($fp) != "\n")
{
if (fseek($fp, -2, SEEK_CUR) == -1)
{
return -1;
}
}
}
答案 2 :(得分:0)
我会这样做:
function readFileFunc($tempFile){
if(@!file_exists($tempFile)){
return FALSE;
}else{
return file($tempFile);
}
}
$textArray = readFileFunc('./data/yourTextfile.txt');
$slicePos = count($textArray)-101;
if($slicePos < 0){
$slicePos = 0;
}
$last100 = array_slice($textArray, $slicePos);
$last100 = implode('<br />', $last100);
echo $last100;
答案 3 :(得分:0)
“位置X”是以行还是字节来衡量的?如果是行,你可以很容易地使用SplFileObject来寻找某一行,然后读取100行:
$file = new SplFileObject('log.txt');
$file->seek(199); // go to line 200
for($i = 0; $i < 100 and $file->valid(); $i++, $file->next())
{
echo $file->current();
}
如果位置X是以字节为单位测量的,那么将初始$offset = -1
更改为其他值不是一件简单的事吗?