1

All,

I cannot for the life of me, figure out why \SplFileObject is repeating the key in the following code. This sample uses Nowdoc as a file stream but this effect can be noted using any file.

PHP Code:

$str = <<<'EOD'
Line 1
Line 2
Line 3
Line 4
Line 5
EOD;

$file = new \SplFileObject('data://text/plain;base64,' . base64_encode($str));
$iterator = call_user_func(function (\SplFileObject $file) {
  while (!$file->eof()) {
    yield [$file->key() => $file->fgets()];
  }
}, $file);

foreach ($iterator as $line) {
  echo key($line) . ': ' . current($line) . PHP_EOL;
}

Output:

0: Line 1
0: Line 2
1: Line 3
2: Line 4
3: Line 5
Curtis
  • 43
  • 1
  • 7
  • `key` gets the current line number and you haven't advanced yet to the next line. – user3942918 Apr 22 '18 at 02:43
  • why not just do this: `$file = new \SplFileObject('data://text/plain;base64,' . base64_encode($str)); foreach($file as $line){ echo $file->key() . ". " . $line; }` https://ideone.com/60kEfB –  Apr 22 '18 at 02:43
  • @smith I'm specifically using the Generator class because, while this sample is small, the file I'm parsing is 500K+ lines long and I'm trying to reduce the memory usage. – Curtis Apr 22 '18 at 02:48
  • @paul-crovella I don't understand why the key is separate from the line. It's not an iteration, it's a method from the SplFileObject class that tells you what line it's reading. If the line advances, so does the key. – Curtis Apr 22 '18 at 02:53
  • 1
    When you call `key` the line has not yet advanced. Your first call to `fgets` doesn't put you on the second line, it puts you at the end of the first. Your second call to `fgets` puts you at the end of the second, and so on. On each iteration you're calling `key` *first*, so the current line is still the same as the previous iteration's `fgets`. – user3942918 Apr 22 '18 at 03:02
  • I too find it weird that key didn't update when it's matching `fgets()` was called; anyway Paul pointed it right it's because the value gets binded and later fgets doesn't affect that binded value, i guess some pass by ref. should solve this – Vinay Apr 22 '18 at 05:36
  • Or... use `yield array_flip([$file->fgets() => $file->key()]);` ;) – Vinay Apr 22 '18 at 06:42

0 Answers0