1

Consider following text file, test.txt:

1
2
3

And following PHP code:

<?php
$file = new SplFileObject('test.txt', 'r');
var_dump($file->key());
$line = $file->fgets();
var_dump($file->key());
$line = $file->fgets();
var_dump($file->key());
$line = $file->fgets();
var_dump($file->key());
$line = $file->fgets();
var_dump($file->key());

It outputs:

int(0) int(0) int(1) int(2) int(3) 

As you can see, key is equally 0 before and after first call to fgets(). Why? Is it intended? Is it a bug?

The behavior is identical setting SplFileObject::READ_AHEAD flag.

I'm using PHP 5.3.10-2

Thank you!

Edit

Looking at SplFileObject source code, it think this is a bug.

Method key() just returns line number:

293 /**
294 * @return line number
295 * @note fgetc() will increase the line number when reaing a new line char.
296 * This has the effect key() called on a read a new line will already
297 * return the increased line number.
298 * @note Line counting works as long as you only read the file and do not
299 * use fseek().
300 */
301 function key()
302 {
303   return $this->lnum;
304 }

Which is stored in lnum instance variable, which is initialized to zero:

26   private $lnum = 0;

When creating a new instance, it seems nothing happens to lnum, so after creating it still should have a 0 value:

32  /**
33  * Constructs a new file object
34  *
35  * @param $file_name The name of the stream to open
36  * @param $open_mode The file open mode
37  * @param $use_include_path Whether to search in include paths
38  * @param $context A stream context
39  * @throw RuntimeException If file cannot be opened (e.g. insufficient
40  * access rights).
41  */
42  function __construct($file_name, $open_mode = 'r', $use_include_path = false,    $context = NULL)
43  {
44    $this->fp = fopen($file_name, $open_mode, $use_include_path, $context);
45    if (!$this->fp)
46    {
47      throw new RuntimeException("Cannot open file $file_name");
48    }
49    $this->fname = $file_name;
50  }

Then, calls to fgets should increase by one lnum ALWAYS, included first time, and this is not what it is happening:

60  /** increase current line number
61  * @return next line from stream
62  */
63  function fgets()
64  {
65    $this->freeLine();
66    $this->lnum++;
67    $buf = fgets($this->fp, $this->max_len);
68  
69    return $buf;
70  }

freelinemethod just is setting another variable to NULL.

Edit 2

I reported a bug to PHP team: https://bugs.php.net/bug.php?id=61523

hakre
  • 193,403
  • 52
  • 435
  • 836
Waiting for Dev...
  • 12,629
  • 5
  • 47
  • 57
  • You should post the code snippets from source code where fgets calls `$this->lnum++`. I suspect the problem may be deeper rooted, but your observation appears valid. – Mike Purcell Mar 26 '12 at 23:37

0 Answers0