dismiss Step into the future! Click here to switch to the beta php.net site
downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | conferences | my php.net

search for in the

fstat> <fscanf
[edit] Last updated: Fri, 28 Jun 2013

view this page in

fseek

(PHP 4, PHP 5)

fseekSeeks on a file pointer

Description

int fseek ( resource $handle , int $offset [, int $whence = SEEK_SET ] )

Sets the file position indicator for the file referenced by handle. The new position, measured in bytes from the beginning of the file, is obtained by adding offset to the position specified by whence.

In general, it is allowed to seek past the end-of-file; if data is then written, reads in any unwritten region between the end-of-file and the sought position will yield bytes with value 0. However, certain streams may not support this behavior, especially when they have an underlying fixed size storage.

Parameters

handle

A file system pointer resource that is typically created using fopen().

offset

The offset.

To move to a position before the end-of-file, you need to pass a negative value in offset and set whence to SEEK_END.

whence

whence values are:

  • SEEK_SET - Set position equal to offset bytes.
  • SEEK_CUR - Set position to current location plus offset.
  • SEEK_END - Set position to end-of-file plus offset.

Return Values

Upon success, returns 0; otherwise, returns -1.

Examples

Example #1 fseek() example

<?php

$fp 
fopen('somefile.txt''r');

// read some data
$data fgets($fp4096);

// move back to the beginning of the file
// same as rewind($fp);
fseek($fp0);

?>

Notes

Note:

If you have opened the file in append (a or a+) mode, any data you write to the file will always be appended, regardless of the file position, and the result of calling fseek() will be undefined.

Note:

Not all streams support seeking. For those that do not support seeking, forward seeking from the current position is accomplished by reading and discarding data; other forms of seeking will fail.

See Also

  • ftell() - Returns the current position of the file read/write pointer
  • rewind() - Rewind the position of a file pointer



fstat> <fscanf
[edit] Last updated: Fri, 28 Jun 2013
 
add a note add a note User Contributed Notes fseek - [32 notes]
up
4
Anonymous
2 years ago
The official docs indicate that not all streams are seekable.
You can try to seek anyway and handle failure:

<?php
if (fseek($stream, $offset, SEEK_CUR) === -1) {
 
// whatever
}
?>

Or, you can use the stream_get_meta_data function:
http://php.net/stream_get_meta_data

<?php
function fseekable($stream) {
 
$meta = stream_get_meta_data($stream);
  return
$meta['seekable'];
}
?>
up
2
seeker at example com
5 years ago
JUST TO QUOTE AND POINT THIS OUT:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3. if you're using fseek() to write data to a file, remember to open the file in "r+"
mode, example:

  $fp=fopen($filename,"r+");

DON'T open the file in mode "a" (for append), because it puts
 the file pointer at the end of the file and doesn't let you
fseek earlier positions in the file (it didn't for me!). Also,
don't open the file in mode "w" -- although this puts you at
the beginning of the file -- because it wipes out all data in
the file.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Took me half a day to figure :/
up
2
lucky at somnius dot com dot ar
6 years ago
Jim's (jim at lfchosting dot com) code for the last-line issue is perfect if the file is not empty, or moreover if it has more than one line. However if the file you're using cotains no new-line character at all (i.e. it is empty or it's got one line and only one) the while loop will stuck indefinitely.

I know this script is meant for big files which would always contain at least several lines, but it would be clever to make the script error-proof.

Thus, here's a little modification to his code.

<?php
function readLastLine ($file) {
   
$fp = @fopen($file, "r");

   
$pos = -1;
   
$t = " ";
    while (
$t != "\n") {
        if (!
fseek($fp, $pos, SEEK_END)) { // *** - fseek returns 0 if successfull, and -1 if it has no succes as in seeking a byte outside the file's range
           
$t = fgetc($fp);
           
$pos = $pos - 1;
        } else {
// ***
           
rewind($fp); // ***
           
break; // ***
       
} // ***
   
}
   
$t = fgets($fp);
   
fclose($fp);
    return
$t;
}
?>

Lines added and/or modified have been marked with "// ***". I hope this helps!

Regards!
up
1
Lutz ( l_broedel at gmx dot net )
8 years ago
Based on the function below, provided by info at o08 dot com (thanks), the following should enable you to read a single line from a file, identified by the line number (starting with 1):

<?
    function readLine ($linenum,$fh) {
        $line = fgets ($fh, 4096);
        $pos = -1;
        $i = 0;

        while (!feof($fh) && $i<($linenum-1)) {
            $char = fgetc($fh);
            if ($char != "\n" && $char != "\r") {
                fseek($fh, $pos, SEEK_SET);
                $pos ++;
            }
            else $i ++;
        }
        $line = fgets($fh);
        return $line;
    } //readLine()
?>
up
1
Anonymous
10 years ago
Don't use filesize() on files that may be accessed and updated by parallel processes or threads (as the filesize() return value is maintained in a cache).
Instead lock the opened file and use fseek($fp,0,SEEK_END) and ftell($fp) to get the actual filesize if you need to perform a fread() call to read the whole file...
up
0
lorenzo dot stanco at gmail dot com
3 months ago
I want to give my contribution about the "read last lines from a file" topic. I've done some researches (starting from here, really) and run many tests for different algorithms and scenarios, and came up with this:

What is the best way in PHP to read last lines from a file?
http://stackoverflow.com/a/15025877/995958

In that mini-article I tried to analyze all different methods and their performance over different files.

Hope it helps.
up
0
Anonymous
1 year ago
I needed to stream a txt file (here big xml file) to get nodes blockwise. I couldn't find a shorter way. So i did write this class.

Function: streams a complete file and returns the content between two search strings with their search strings (multi byte safe)

Hope it helps anyone.

PS: It lacks any boolean checks / exception handling for non existing files / read errors.

<?php
/**
 * Reads txt-files blockwise
 * Usage:
    $c_streamFileTxt = new streamFileTxt;
    $_args = array(

        'file' => 'temporary.xml',
        'start_string' => '<Product>',
        'stop_string' => '</Product>',
        'block_size' => '8192'
    );
   
    $c_streamFileTxt->setArgs($_args);

    while ($txt_block = $c_streamFileTxt->getNextBlock())
    {
        // use $txt_block for something
    }
 */

class streamFileTxt
{
    private
$handle;
    private
$file;
    private
$file_offset;
    private
$block;
    private
$start_string;
    private
$stop_string;
    private
$block_size;

   
/**
     * Sett class arguments
     * @param array $_args
     */
   
public function setArgs($_args)
    {
       
$this->file = $_args['file'];
       
$this->start_string = $_args['start_string'];
       
$this->stop_string = $_args['stop_string'];
       
$this->block_size = $_args['block_size'];
    }

   
/**
     * Get next textblock within a file
     * @param void
     * @return string $textblock
     */
   
public function getNextBlock()
    {
       
$this->openFile();

       
fseek($this->handle, $this->file_offset);
       
$start_string_found = false;
       
$stop_string_found = false;
        while (!
feof($this->handle))
        {
           
$txt_block = fread($this->handle, $this->block_size);

            if (!
$start_string_found) // while not start start snippet found
           
{
               
$strpos = mb_strpos($txt_block, $this->start_string);
                if (
$strpos !== false)
                {
                   
// cut of first left chunk
                   
$txt_block = mb_substr($txt_block, $strpos, $this->block_size);
                   
$start_string_found = true;
                }
            }

            if (
$start_string_found && !$stop_string_found) // start snipped found, looking for stop snippet
           
{
               
$strpos = mb_strpos($txt_block, $this->stop_string);
                if (
$strpos !== false)
                {
                   
$removed_block_size = mb_strlen($txt_block) - $strpos;
                   
$txt_block = mb_substr($txt_block, 0, $strpos + mb_strlen($this->stop_string));
                   
$stop_string_found = true;
                   
$this->setFileOffset($removed_block_size);
                }
            }

            if (
$stop_string_found) // stop-snippet found, keep file offset, return
           
{
               
$this->closeFile();
                return
$txt_block;
            }
        }

       
$this->closeFile();
        return
false;
    }
   
   
/**
     * Set current file offset and consider the removed block size
     * current file position = current file offset - removed block size
     * @param int $removed_block_size
     */
   
private function setFileOffset($removed_block_size)
    {
       
$this->file_offset = ftell($this->handle) - $removed_block_size;
    }
   
   
/**
     * close current file
     * @param void
     * @return void
     */
   
private function openFile()
    {
       
$this->handle = fopen($this->file, 'r');
    }
   
   
/**
     * open file
     * @param void
     * @return void
     */
   
private function closeFile()
    {
       
fclose($this->handle);
    }
}
up
0
kavoshgar3 at gmail dot com
1 year ago
sometimes we want read file from last line to beginning of file.I use the following.
<?php
function read_backward_line($filename, $lines, $revers = false)
{
   
$offset = -1;
   
$c = '';
   
$read = '';
   
$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"));
}
//if $revers=false function return->
//line 1000: i am line of 1000
//line 1001: and i am line of 1001
//line 1002: and i am last line
//but if $revers=true function return->
//line 1002: and i am last line
//line 1001: and i am line of 1001
//line 1000: i am line of 1000
?>
Enjoy! Mail me if it works!  ;-)
up
0
Anonymous
5 years ago
To:seeker at example com
Be careful, though.
You can freely position you pointer if you open a file in (r+) mode, but it will "overwrite" the data, not "append it".

Tested this:

<?php
// file.txt content:
// "You can contribute your notes to the PHP manual from the comfort of your browser!"

$handler = fopen("file.txt", "r+");
fseek($handler, 0);
fwrite($handler, "want to add this");
?>
New contents of the file.txt will be like this:
"want to add thiste your notes to the PHP manual from the comfort of your browser!".

If you really want to append at the beginning, you have to first get all the contents, save it, clear the file, put the new contents and append the saved contents at the end.
up
0
mhinks at gmail dot com
6 years ago
Here's a function I wrote to binary search for a line of text within a file, particularly useful when the file is too large to read into memory at once and you want a faster search than linear.

function binary_search_in_file($filename, $search) {

    //Open the file
    $fp = fopen($filename, 'r');

    //Seek to the end
    fseek($fp, 0, SEEK_END);

    //Get the max value
    $high = ftell($fp);
   
    //Set the low value
    $low = 0;

    while ($low <= $high) {
        $mid = floor(($low + $high) / 2);  // C floors for you

        //Seek to half way through
        fseek($fp, $mid);

        if($mid != 0){
            //Read a line to move to eol
            $line = fgets($fp);
        }
       
        //Read a line to get data
        $line = fgets($fp);
       

        if ($line == $search) {
            fclose($fp);
            return $line;
        }
        else {
            if ($search < $line) {
                $high = $mid - 1;
            }
            else {
                $low = $mid + 1;
            }
        }
    }

    //Close the pointer
    fclose($fp);

    return FALSE;

}
up
0
marc dot roe at gmail dot com
6 years ago
I tried to improve and modify (mail at ulf-kosack dot de)'s function. Actually it is very fast, i.e. requires much less time than to get the last five, ten or whatever lines of a file using file() ore file_get_contents().

function read_file($file, $lines)
{
       $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); // array_reverse is optional: you can also just return the $text array which consists of the file's lines.
}

The good thing now is, that you don't get an error when your requesting more lines than the file contains. In this case the function will just return the whole file content.
up
0
dan at daniellampert dot com
11 years ago
For all first-time users of the fseek() function, remember these three things:

1. to use a programming expression, fseek() is "base 0", so to prepare the file for writing at character 1, you'd say fseek($fp,0); and to prepare the file for writing at character $num, you'd say fseek($fp,($num-1));

2. here's the formula for accessing fixed-length records in a file (you need to seek the position of the end of the previous record):

  /* assumes the desired record number is in $rec_num */
  /* assumes the record length is in $rec_len */
  $pos = ( ($rec_num-1) * $rec_len );
  fseek($fp,$pos);

3. if you're using fseek() to write data to a file, remember to open the file in "r+" mode, example:

  $fp=fopen($filename,"r+");

Don't open the file in mode "a" (for append), because it puts the file pointer at the end of the file and doesn't let you fseek earlier positions in the file (it didn't for me!). Also, don't open the file in mode "w" -- although this puts you at the beginning of the file -- because it wipes out all data in the file.

Hope this helps.
up
-1
vidmantas dot norkus at uostas dot net
4 years ago
read x lines from log file end

marc dot roe at gmail dot com improved a bit speed
but this makes reading even more faster :)

test on my server:
2megs file with his function read elapsed 5 sec vs mines 0.03 sec

faster with large and small file

<?php
function __file_backread_helper(&$haystack,$needle,$x)
{
   
$pos=0;$cnt=0;   
    while(
$cnt < $x && ($pos=strpos($haystack,$needle,$pos)) !==false ){$pos++;$cnt++;}   
    return
$pos==false ? false:substr($haystack,$pos,strlen($haystack));
}

function
file_backread($file,$lines,&$fsize=0){
   
$f=fopen($file,'r');
    if(!
$f)return Array();
   
   
   
$splits=$lines*50;
    if(
$splits>10000)$splits=10000;

   
$fsize=filesize($file);
   
$pos=$fsize;
   
   
$buff1=Array();
   
$cnt=0;

    while(
$pos)
    {
       
$pos=$pos-$splits;
       
        if(
$pos<0){ $splits+=$pos; $pos=0;}

       
fseek($f,$pos);
       
$buff=fread($f,$splits);
        if(!
$buff)break;
       
       
$lines -= substr_count($buff, "\n");

        if(
$lines <= 0)
        {
           
$buff1[] = __file_backread_helper($buff,"\n",abs($lines)+1);
            break;
        }
       
$buff1[] = $buff;
    }

    return
str_replace("\r",'',implode('',array_reverse($buff1)));
}
?>

end of dirty code
up
0
necudeco at gmail dot com
2 years ago
This a tail php script example for windows system.

<?php
$n
= ( isset($_REQUEST['n']) == true )? $_REQUEST['n']:20;

$offset = -$n * 120;

$rs = fopen('C:/wamp/logs/apache_error.log','r');
if (
$rs === false )
    die(
"No se pudo abrir el archivo de log");

fseek($rs,$offset,SEEK_END);

fgets($rs);
while(!
feof($rs))
{
   
$buffer = fgets($rs);
    echo
$buffer;
    echo
"<hr />";
}

fclose($rs);
?>
up
0
steve at studio831 dot com
3 years ago
Modified @ben's function to work for files larger than PHP_INT_MAX bytes.

<?php
function longTail($file, $numLines = 100)
{
   
$fp = fopen($file, "r");
   
$chunk = 4096;
   
$fs = sprintf("%u", filesize($file));
   
$max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : filesize($file);

    for (
$len = 0; $len < $max; $len += $chunk) {
       
$seekSize = ($max - $len > $chunk) ? $chunk : $max - $len;

       
fseek($fp, ($len + $seekSize) * -1, SEEK_END);
       
$data = fread($fp, $seekSize) . $data;

        if (
substr_count($data, "\n") >= $numLines + 1) {
           
preg_match("!(.*?\n){".($numLines)."}$!", $data, $match);
           
fclose($fp);
            return
$match[0];
        }
    }
   
fclose($fp);
    return
$data;
}
?>
up
0
Tom Pittlik
4 years ago
The tail example functions below will return a PHP memory limit error when trying to open large files. Since tail is convenient for opening large logs, here is a function that lets you (provided you have permission):

<?php

function unix_tail($lines,$file)
{
   
shell_exec("tail -n $lines $file > /tmp/phptail_$file");
   
$output = file_get_contents("/tmp/phptail_$file");
   
unlink("/tmp/phptail_$file");
    return
$output;
}

?>
up
0
ben at nullcreations dot net
4 years ago
easier tail() function for php:

<?php
function tail($file, $num_to_get=10)
{
 
$fp = fopen($file, 'r');
 
$position = filesize($file);
 
fseek($fp, $position-1);
 
$chunklen = 4096;
  while(
$position >= 0)
  {
   
$position = $position - $chunklen;
    if (
$position < 0) { $chunklen = abs($position); $position=0;}
   
fseek($fp, $position);
   
$data = fread($fp, $chunklen). $data;
    if (
substr_count($data, "\n") >= $num_to_get + 1)
    {
      
preg_match("!(.*?\n){".($num_to_get-1)."}$!", $data, $match);
       return
$match[0];
    }
  }
 
fclose($fp);
  return
$data;
}
?>
up
0
mail at ulf-kosack dot de
7 years ago
Here a little extension for the code of ekow.
If you want to read more than one line and more than one file. Some times the last five ore ten lines are interesting in.

You only have to submit a array with filenames and optionally a number of lines you want to read.

<?php
 
function read_logfiles($files, $lines=5)
  {
    foreach(
$files as $file_num => $file) {
      if (
file_exists ($file) ) {
       
$handle = fopen($file, "r");
       
$linecounter = $lines;
       
$pos = -2;
       
$t = " "
       
$text[$file_num] = "";
        while (
$linecounter > 0) {
          while (
$t != "\n") {
           
fseek($handle, $pos, SEEK_END);
           
$t = fgetc($handle);
           
$pos --;
          }
         
$t = " ";
         
$text[$file_num] .= fgets($handle);
         
$linecounter --;
        }
       
fclose ($handle);
      } else {
       
$text[$file_num] = "The file doesn't exist.";
      }
    }
   
    return
$text;
?>
up
0
ekow[at]te.ugm.ac.id
7 years ago
A little correction for code to read last line from chenganeyou at eyou dot com.
$linenumber = sizeof($file)-1;
should be
$linenumber = sizeof($contents)-1;
because sizeof will count array element, not file size.
<?php
function readlastline($file)
{
      
$linecontent = " ";
      
$contents = file($file);
      
$linenumber = sizeof($contents)-1;
      
$linecontet = $contents[$linenumber];
       unset(
$contents,$linenumber);
       return
$linecontent;
}
?>
up
0
chenganeyou at eyou dot com
8 years ago
I use the following codes to read the last line of a file.
Compared to jim at lfchosting dot com, it should be more efficient.

<?php
function readlastline($file)
{
      
$linecontent = " ";
      
$contents = file($file);
      
$linenumber = sizeof($file)-1;
      
$linecontet = $contents[$linenumber];
       unset(
$contents,$linenumber);
       return
$linecontent;
}
?>
up
0
phil at NOSPAM dot blisswebhosting dot com
8 years ago
In order to read a text file from end->beginning e.g display the most recent contents of a log file first.  I use the following.

It basically just uses fseek to find the end of the file, ftell to find the byte count for a counter, then iterates backwards through the file using fgetc to test for the newline charater.

$i=0 ;
$lines=500 ;
$fp = fopen($log,"r") ;
if(is_resource($fp)){
    fseek($fp,0,SEEK_END) ;
    $a = ftell($fp) ;
    while($i <= $lines){
        if(fgetc($fp) == "\n"){
            echo (fgets($fp));
            $i++ ;
        }
    fseek($fp,$a) ;
    $a-- ;
    }
}
up
0
alan at peaceconstitution.com
8 years ago
Thanks to Dan, whose above comment provided a key to solve the issue of how to append to a file.
     After, using phpinfo(); I made sure my installation of PHP had the requisite settings mentioned in the text to the manual entry for fopen(), I was puzzled as to why my use of fopen() with the append option 'a' (append option) didn't work. Then I  read a comment contributed to Appendix L (http://us2.php.net/manual/en/wrappers.php) that the append option 'a' for fopen() doesn't work as expected. The writer suggested using the 'w' option instead, which I found did work. But the 'w' option (write option) overwrites everything in the file.
     The question remained how to accomplish appending. Following Dan's suggestion about the 'r+' option, I tried this, which works fine:
       $string = "Message to write to log";
       $filehandle = fopen ("/home/name/sqllogs/phpsqlerr.txt", 'r+');
    fseek ( $filehandle,0, SEEK_END);
    fwrite ( $filehandle, $string."\n" );
    fclose ($filehandle);
up
0
info at o08 dot com
9 years ago
I think the function should be as following to deal any combination of cr & lf, no matter the line ends by cr, lf, cr-lf or lf-cr:

<?php
function getline ($handle) {
       while (!
feof($handle)) {
          
$char = fgetc($handle);
           if ((
$char == "\n") or ($char == "\r")) {
              
$char2 = fgetc($handle);
               if ((
$char2 != "\n") && ($char2 != "\r")) {
                  
fseek ($handle,-1,SEEK_CUR);
               }
               break;
           }
           else {
              
$buffer .= $char;
           }
       }
       return
$buffer;
}
?>
up
0
jim at lfchosting dot com
9 years ago
Here is a function that returns the last line of a file.  This should be quicker than reading the whole file till you get to the last line.  If you want to speed it up a bit, you can set the $pos = some number that is just greater than the line length.  The files I was dealing with were various lengths, so this worked for me.

<?php
function readlastline($file)
{
       
$fp = @fopen($file, "r");
       
$pos = -1;
       
$t = " ";
        while (
$t != "\n") {
             
fseek($fp, $pos, SEEK_END);
             
$t = fgetc($fp);
             
$pos = $pos - 1;
        }
       
$t = fgets($fp);
       
fclose($fp);
        return
$t;
}
?>
up
-1
serg at red-sign dot ru
7 months ago
SOLUTION FOR BIG FILES (2GB SEEK BUGFIX)

when you using files larger than 2gb
you are in big fail with standard solution like:
fseek($fs,4*1024*1024*1024); // 4GB

<?php
//But this work perfect:
while(!feof($fs)){
    echo
''.($i++).'<br/>';
   
$data = fread($fs,$package);
}

//its follow to use this solution for 2gb+ files read:

for($i=0;$i<$page;$i++){
   
fseek($fs,$package_len,SEEK_CUR);
}
?>

good luck for all :)
up
-1
Nitrogen
2 years ago
Guys, I have always had issues with PHP's internally signed integers..
I design my own database structures and I store huge amounts of data in files (over 100 GBs) and I've always had issues doing anything with a file past the 2 GB mark.

I did some testing and discovered the limit of fseek/ftell and/or any other integer operation.
The limit is 2 GBs minus 1 byte.. or 2×1024³-1 (or 2*pow(1024,3)-1).

I had to make a work-around because of this and split my database into multiple files to avoid this problem.. works just fine now.
I didn't see the signed integer issue mentioned with this function so I thought I would, may save someone the time figuring it out, too.

Nitrogen.
up
-1
Max Christian Pohle
3 years ago
This example demonstrates, how fseek can be used to determine the dimension (size) of an mp4-video-file:

<?php
  $fh
; # filehandle
 
if(($fh = fopen($filename, "rb")) === FALSE)
  { die(
"unable to open file '$filename'!"); }

 
# seek headerposition, where sizeX is...
 
fseek($fh, 0xE8);
 
$sizeX = fread($fh, 2); # read two bytes (the width)

  # seek headerposition, where sizeY is...
 
fseek($fh, 0xEC);
 
$sizeY = fread($fh, 2); # read two bytes (the height)

 
fclose($fh);

  echo
"sizeX: ".hexdec(bin2hex($sizeX))."<br/>";
  echo
"sizeX: ".hexdec(bin2hex($sizeY))."<br/>";
?>
up
-1
jeffunk7 at yahoo dot com
7 years ago
If you, like me, need the second to last line from a text file (or some other line near the end that you will know the number of, ie the fourth to last line) then this addition to Jim's code can help you.

//$linefromlast is the linenumber that you need, the last line being 1, the second to last being 2, and so on...

function readlog($file, $linefromlast){
   $fp = @fopen($file, "r");
   $pos = -2;
   $t = " ";
   $linecounter = 1;
        while ($t != "\n" and $linecounter<=$linefromlast) {
                fseek($fp, $pos, SEEK_END);
                $t = fgetc($fp);
                $pos = $pos - 1;
                if ($t == "\n" and $linecounter < $linefromlast) {
                        fseek($fp, $pos, SEEK_END);
                        $t = fgetc($fp);
                        $pos = $pos - 1;
                        $linecounter = $linecounter +1;
                }
         }
    $t = fgets($fp);
    fclose($fp);
    return $t;
}
up
-1
memphis
7 years ago
Actually chenganeyou, your function causes the entire file to be read into an array, and then you look at the last element of the array.  While this works fine for a small file, an sizeable file is going to suck down memory and time.  Using a 15 MB file your function took around 2 secs to return.

The function provided by Jim goes directly to the end of the file and only reads in that line.  I had to set the offset ($pos) to -2 for it to work in my case however.  Using the same 15 MB file this function returns immediately.
up
-1
aspyrine at hotmail dot com
10 years ago
If you want to go to the end of a socket stream with fseek() you'll get the following error :
"stream does not support seeking"

feof() wont work eiver in a stream (ie. smtp)

You can move the pointer to the end with this command :
while(fgetc($fp)) {}
...so easy :-)
up
-2
sylvain at abstraction dot fr
2 years ago
seeking past PHP_INT_MAX.

<?php

function fseek64(&$fh, $offset)
{
   
fseek($fh, 0, SEEK_SET);

    if (
$offset <= PHP_INT_MAX)
    {
        return
fseek($fh, $offset, SEEK_SET);
    }

   
$t_offset   = PHP_INT_MAX;
   
$offset     = $offset - $t_offset;

    while (
fseek($fh, $t_offset, SEEK_CUR) === 0)
    {
        if (
$offset > PHP_INT_MAX)
        {
           
$t_offset   = PHP_INT_MAX;
           
$offset     = $offset - $t_offset;
        }
        else if (
$offset > 0)
        {
           
$t_offset   = $offset;
           
$offset     = 0;
        }
        else
        {
            return
0;
        }
    }

    return -
1;
}

?>
up
-2
Anonymous
10 years ago
The following call moves to the end of file (i.e. just after the last byte of the file):

    fseek($fp, 0, SEEK_END);

It can be used to tell the size of an opened file when the file name is unknown and can't be used with the filesize() function:

    fseek($fp, 0, SEEK_END);
    $filesize = ftell($fp);

The following call moves to the begining of file:

    fseek($fp, 0, SEEK_SET);

It is equivalent to:

    rewind($fp);

 
show source | credits | stats | sitemap | contact | advertising | mirror sites