PHP:从文件中的某个点读取

duk*_*vin 5 php pagination file fseek

类似于:如何在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"));
}
Run Code Online (Sandbox Code Playgroud)

我要做的是创建一个基于Web的日志查看器,它将从文件末尾开始并显示100行,当按下"下一步"按钮时,将显示其前面的下一行.

Dev*_*ant 3

这用于fseek从指定偏移量开始读取文件的 100 行。如果偏移量大于日志中的行数,则读取前 100 行。

在您的应用程序中,您可以通过prevnext 的查询字符串传递当前偏移量,并以此为基础下一个偏移量。您还可以存储并传递当前文件位置以提高效率。

<?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;
      }
   }
}
Run Code Online (Sandbox Code Playgroud)