php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68466 Iterating SplFileObject shows empty line at end of file
Submitted: 2014-11-20 20:48 UTC Modified: 2022-02-12 02:10 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: tim_siebels_aurich at yahoo dot de Assigned:
Status: Open Package: SPL related
PHP Version: 5.6.3 OS:
Private report: No CVE-ID: None
 [2014-11-20 20:48 UTC] tim_siebels_aurich at yahoo dot de
Description:
------------
Iterating over a SplFileObject differs from using fopen() and friends.
SplFileObject is supposed to be an object oriented interface for the file handling functions. Their output shouldn't be different.



Test script:
---------------
<?php
$o = new SplFileObject(__FILE__);

foreach($o as $key=>$val) {
  var_dump($val);
}

/*
Should be the same as

$h = fopen(__FILE__, 'r');

while(!feof($h)) {
  var_dump(fgets($h));
}

*/

Expected result:
----------------
string(3) "<?
"
string(34) "$o = new SplFileObject(__FILE__);
"
string(1) "
"
string(28) "foreach($o as $key=>$val) {
"
string(18) "  var_dump($val);
"
string(2) "}
"
bool(false)

Actual result:
--------------
<?php

$o = new SplFileObject(__FILE__);

foreach($o as $key=>$val) {
  var_dump($val);
}

Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-11-22 22:44 UTC] fmargaine@php.net
Hi,

This is the equivalent you're looking for:

<?php
$o = new SplFileObject(__FILE__);

while (!$o->eof()) {
  var_dump($o->fgets());
}

?>

However, it *is* weird that the iterator doesn't stop at the end of file.
 [2014-11-22 23:21 UTC] fmargaine@php.net
-Assigned To: +Assigned To: fmargaine
 [2014-11-22 23:38 UTC] fmargaine@php.net
I can't actually reproduce having bool(false) at the end. On a clean build (5.5/5.6), SplFileObject iterates correctly.
 [2014-11-22 23:38 UTC] fmargaine@php.net
-Assigned To: fmargaine +Assigned To:
 [2014-11-22 23:53 UTC] tim_siebels_aurich at yahoo dot de
It sure does. But it is different from the fopen variation.

Take a second look at expected/actual. 

I expect to have false at the end, because if you use fopen() you get false at the end. Either of those should be changed.
 [2014-11-23 00:13 UTC] requinix@php.net
You need a trailing newline at the end of the file.

The regular file functions work on streams, not literally files. You have to try to read past the end of the stream before feof() will know to return true. However when fread() reads the last time there is nothing left so it returns false.
SplFileObject works on streams too but entire lines at a time. It also considers an empty line to still be a line, which is why it returns "" instead of false - which fits with how most text editors treat trailing newlines too.

I don't consider this to be a bug since (1) as fmargaine said the two code chunks are not actually equivalent, and (2) the two methods read files in a slightly different way.
 [2014-11-23 12:06 UTC] tim_siebels_aurich at yahoo dot de
To (1):
  fmargaine also provided an equivalent snippet, that doesn't match the output.

To (2):
  Of course they do, that's why I opened this bug :P
  I don't really understand why SplFileObject works differently. 
  
  > SplFileObject works on streams too but entire lines at a time.

  SplFileObject has methods that map the name from fopen and friends. 
  As far as I know SplFileObject doesn't use entire lines. 
  I can SplFileObject::fread from it as well.
  fgets() uses entire lines as well, but the output still differs.  

I see why it is good to have it when iterating over the SplFileObject. Otherwise every last line would be false.
However, I don't see why they should be different. I expect them to be the same. They provide the same functionality and even the same names.
 [2016-06-21 22:39 UTC] cmb@php.net
> I see why it is good to have it when iterating over the
> SplFileObject. Otherwise every last line would be false.
> However, I don't see why they should be different. I expect them
> to be the same. They provide the same functionality and even the
> same names.

So you really think the more useful behavior should be changed for
the sake of consistency with rather low-level (C'ish) behavior?
I'd rather change the names of the methods instead. Neither is
obviously something that can be easily done with regard to
backward compatibility, though.
 [2022-02-12 02:10 UTC] requinix@php.net
-Block user comment: No +Block user comment: Yes
 [2024-03-09 11:05 UTC] marriclejohn1 at gmail dot com
The following pull request has been associated:

Patch Name: Added a confirm prompt to Subscribe/Unsubscribe button
On GitHub:  https://github.com/php/web-bugs/pull/86
Patch:      https://github.com/php/web-bugs/pull/86.patch
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 14:01:29 2024 UTC