SoFunction
Updated on 2025-03-10

Recommended efficient method for reading N lines at the end of a large file

Small files with a size of less than a few megabytes can be read into an array by line through the file() function, and then use array_pop to get the last line.

However, for large text files, the machine memory is not large enough, or there are restrictions on memory_limit on php itself, this method is not applicable. Even if it is forced to do not limit, the efficiency is very low.

Is there no way? Of course there are, but there are no ready-made functions, so you need to do it yourself.

File pointers are needed here. Those who have learned C should know the pointer type. In layman's terms, a file is opened through fopen in PHP. At this time, the file is not read yet. At this time, it points to the beginning of the file, and the pointer position is 0. When you read content from the file through fgets or fgetc, how much do you read and how much pointer moves forward accordingly. This is also

while(!feof($fp)){
$data.=fgets($fp,4096);
}

The principle that is implemented is that fgets is to read a string of specified length backward from the current pointer position until a newline is encountered.

So can we control the position of the pointer to the Nth row last? Unfortunately, there is no, but you can move the pointer directly to the end and go back N positions through the fseek() function.

We first move the pointer to the end and backwards by 2 positions. Read a character through fgetc to determine whether this character is "\n", that is, a newline. If it is not a newline, then continue to go backwards and judge again until we go back to the end of the previous line, and use fgets to get the entire line out. Two while loops are used here. The outer loop controls the number of rows that need to be obtained, and the inner loop controls the fseek action.

The function is as follows:

/**
  * Get the last $n line of the file
  * @param string $filename file path
  * @param int $n Last lines
  * @return mixed false means there is an error, and if successful, return the string
  */
function FileLastLines($filename,$n){
  if(!$fp=fopen($filename,'r')){
    echo "The file failed to open. Please check whether the file path is correct. Do not include Chinese in the path and file name";
    return false;
  }
  $pos=-2;
  $eof="";
  $str="";
  while($n>0){
    while($eof!="\n"){
      if(!fseek($fp,$pos,SEEK_END)){
        $eof=fgetc($fp);
        $pos--;
      }else{
        break;
      }
    }
    $str.=fgets($fp);
    $eof="";
    $n--;
  }
  return $str;
}
echo nl2br(FileLastLines('',4));

The above efficient method of reading N lines at the end of a large file is the entire content I share with you. I hope you can give you a reference and I hope you can support me more.