php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48420 stream_get_line() - invalid result when passing $length and $ending
Submitted: 2009-05-28 22:21 UTC Modified: 2009-06-01 19:03 UTC
From: ryan dot brothers at gmail dot com Assigned:
Status: Not a bug Package: Streams related
PHP Version: 5.*, 6CVS(2009-05-29) OS: Linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: ryan dot brothers at gmail dot com
New email:
PHP Version: OS:

 

 [2009-05-28 22:21 UTC] ryan dot brothers at gmail dot com
Description:
------------
When you pass to stream_get_line() a $length that is greater than the file size and a $ending that does not appear in the file, stream_get_line() returns bool(false) rather than the string that is in your file.

In the below example, when I run stream_get_line() passing in a $length of 6 and a $ending of "\n", stream_get_line() returns false rather than the contents of the file.

The manual states "Reading ends when length bytes have been read, when the string specified by ending is found (which is not included in the return value), or on EOF (whichever comes first).", so I believe the contents of my file should be returned since EOF is first to be reached.

Reproduce code:
---------------
<?php
$fp = tmpfile();

fwrite($fp, '12345');

fseek($fp, 0);
var_dump(stream_get_line($fp, 5));

fseek($fp, 0);
var_dump(stream_get_line($fp, 6));

fseek($fp, 0);
var_dump(stream_get_line($fp, 5, "\n"));

fseek($fp, 0);
var_dump(stream_get_line($fp, 6, "\n"));

fclose($fp);


Expected result:
----------------
string(5) "12345"
string(5) "12345"
string(5) "12345"
string(5) "12345"


Actual result:
--------------
string(5) "12345"
string(5) "12345"
string(5) "12345"
bool(false)


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-05-29 08:39 UTC] lbarnaud@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.3-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/


 [2009-05-29 09:00 UTC] lbarnaud@php.net
Verified. Actually this may be expected.

<?php
fseek($fp, 0);
var_dump(stream_get_line($fp, 6, "\n"));
?>

If stream_get_line() reads only 5 bytes here there is no way to tell if this is the end of the stream (without re-reading from the stream, which would block on sockets, etc). So it can't find the end of the line and return false.

The next call to stream_get_line() will mark the stream as EOF, and stream_get_line will return the line:

<?php
$fp = tmpfile();
fwrite($fp, '12345');
fseek($fp, 0);

while (!feof($fp)) {
 $line = stream_get_line($fp);
 if ($line === false) continue;
 var_dump($line);
}
?>

Result:
string(5) "12345"
 [2009-05-29 13:09 UTC] ryan dot brothers at gmail dot com
Thanks for your feedback.  I tried it on the latest PHP 5.3 snapshot and got the same results.

I noticed though when I run this:

<?php
fseek($fp, 0);
var_dump(fgets($fp, 6));

fseek($fp, 0);
var_dump(fgets($fp, 7));
?>

I get the expected results of:

string(5) "12345"
string(5) "12345"

Since the manual page for stream_get_line() states that this function is identical to fgets() except for handling of the delimiter, should stream_get_line() return the same results as fgets() for this case since my delimiter is a newline?

Also, I'm not sure why these 2 calls to stream_get_line() return different output:

<?php
fseek($fp, 0);
var_dump(stream_get_line($fp, 6));

fseek($fp, 0);
var_dump(stream_get_line($fp, 6, "\n"));
?>

Result:

string(5) "12345"
bool(false)
 [2009-06-01 13:03 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

Because the file is still open there is no EOF, so the stream_get_line() 
cannot find the line's end and there is no EOF, thus it returns false.
 [2009-06-01 19:03 UTC] ryan dot brothers at gmail dot com
Thanks for your reply.  Shouldn't stream_get_line() find the EOF since it will read the first 5 characters and then find the EOF when trying to read the next character since $length = 6?  Also, if what you wrote is the case, I'm not sure why this:

<?php
$fp = tmpfile();

fwrite($fp, "12345");

fseek($fp, 0);
var_dump(stream_get_line($fp, 6, "\n"));
?>

returns:

bool(false)

but this works successfully:

<?
$fp = tmpfile();

fwrite($fp, "12345\n67890");

fseek($fp, 0);
var_dump(stream_get_line($fp, 6, "\n"));
var_dump(stream_get_line($fp, 6, "\n"));
?>

returns:

string(5) "12345"
string(5) "67890"

On the 2nd call to stream_get_line(), there are 5 bytes remaining to be read, $length = 6, and there are no \n's remaining, which is the same exact scenario as my first example above.  In my first example, stream_get_line() returns false, but in the 2nd example, stream_get_line() returns the expected string - should both of these calls have the same results?

I encountered this issue when trying to use stream_get_line() to parse very large text files reading in each file in sections delimited by a string delimiter, but one of my text files did not contain this delimiter and stream_get_line() returned false for that file which I don't believe was correct.  I was expecting it to read in the entire file since $length was greater than the size of the file, which is what the documentation says should occur.

Thanks again for your assistance.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Apr 24 14:01:30 2024 UTC