the output of ftell in php function
Asked Answered
B

4

18

Here is my code:

<?php
    $url="http://www.sina.com.cn";
    $handle = @fopen($url, "r");
    $len=get_headers($url,true);
    print_r($len);
    echo $len['Content-Length']."\n";
    if ($handle) {
        while (($buffer = fgets($handle,1024)) !== false) {
            echo ftell($handle)."\n";
            fseek($handle,200000,SEEK_CUR);
            echo ftell($handle)."\n";
        }
        if (!feof($handle)) {
            echo "Error: unexpected fgets() fail\n";
        }
        fclose($handle);
    }
?>

The result is as below:

    Array
(
    [0] => HTTP/1.1 200 OK
    [Content-Type] => text/html
    [Vary] => Accept-Encoding
    [X-Powered-By] => shci_v1.03
    [Server] => nginx
    [Date] => Thu, 24 Dec 2015 04:03:39 GMT
    [Last-Modified] => Thu, 24 Dec 2015 04:01:28 GMT
    [Expires] => Thu, 24 Dec 2015 04:04:39 GMT
    [Cache-Control] => max-age=60
    [Age] => 32
    [Content-Length] => 518264
    [X-Cache] => HIT from xidan33-99.sina.com.cn
    [Connection] => close
)
518264
16
200016
200058
400058
400065
518264

The Content-Length maybe not the same as mine--518264,it will be changed dynamically when you execute the code,it does no matter for the discussion. Why the result is not the following?

518264
1024
201024
202048
402048
403072

please explain the action of file pointer on fgets and ftell and fseek function .

Briolette answered 24/12, 2015 at 2:16 Comment(0)
A
7

As per the PHP documentation for fgets(),

Reading ends when length - 1 bytes have been read, or a newline (which is included in the return value), or an EOF (whichever comes first).

Here length is the 2nd parameter you have used when calling fgets(), which is 1024. So your call to fgets() will end reading when any of the following happens :

  1. It has read 1023 bytes from the same line.
  2. It has reached the end of current line.
  3. It has reached the end of file.

So, in your case, when fgets() reads the first line it reached the end of the first line after reading 16 bytes, and that will be the position of the file pointer when called by ftell() next to it. ftell() returns the current position of the file pointer in the file.

When you are in the next line calling the fgets()again (iterated by the while loop), your starting position in the file is now 16 (notably not 1024) and you can read upto (16 + 1024) 1040 bytes (not upto 2048). Again if your next line has only 42 bytes, this fgets() will end reading at 58 bytes, which will be the position of the file pointer when called by ftell() again.

And again you are going to start next fgets() from 58 bytes, to read up to (58 + 1024 =) 1082 bytes. It will continue this way.

Effect of fseek()
fseek() is used to move the file pointer to a specific position in the file as set by the $offset (2nd paramater). According to the PHP documentation for fseek(), the 3rd parameter values can be -

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.

So, by fseek($handle,200000,SEEK_CUR); you are setting the file pointer to be at 200000 + the current position. For example, it will move to 200016 when it was in 16.

Ailyn answered 28/12, 2015 at 3:59 Comment(0)
N
10

The length parameter of fgets indicates a maximum length. The PHP documentation states:

Reading ends when length - 1 bytes have been read, or a newline (which is included in the return value), or an EOF (whichever comes first). If no length is specified, it will keep reading from the stream until it reaches the end of the line.

In your case, the first line contains <!DOCTYPE html>, which explains the result of 16 given by ftell.

Norinenorita answered 24/12, 2015 at 3:28 Comment(0)
A
7

As per the PHP documentation for fgets(),

Reading ends when length - 1 bytes have been read, or a newline (which is included in the return value), or an EOF (whichever comes first).

Here length is the 2nd parameter you have used when calling fgets(), which is 1024. So your call to fgets() will end reading when any of the following happens :

  1. It has read 1023 bytes from the same line.
  2. It has reached the end of current line.
  3. It has reached the end of file.

So, in your case, when fgets() reads the first line it reached the end of the first line after reading 16 bytes, and that will be the position of the file pointer when called by ftell() next to it. ftell() returns the current position of the file pointer in the file.

When you are in the next line calling the fgets()again (iterated by the while loop), your starting position in the file is now 16 (notably not 1024) and you can read upto (16 + 1024) 1040 bytes (not upto 2048). Again if your next line has only 42 bytes, this fgets() will end reading at 58 bytes, which will be the position of the file pointer when called by ftell() again.

And again you are going to start next fgets() from 58 bytes, to read up to (58 + 1024 =) 1082 bytes. It will continue this way.

Effect of fseek()
fseek() is used to move the file pointer to a specific position in the file as set by the $offset (2nd paramater). According to the PHP documentation for fseek(), the 3rd parameter values can be -

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.

So, by fseek($handle,200000,SEEK_CUR); you are setting the file pointer to be at 200000 + the current position. For example, it will move to 200016 when it was in 16.

Ailyn answered 28/12, 2015 at 3:59 Comment(0)
B
3

Three functions are available for setting and determining the position of the file pointer for a given file.

fgets()

Gets a line from file pointer. it would assume 1024 as the line length. If the majority of the lines in the file are all larger than 8KB, it is more resource efficient for your script to specify the maximum line length.

Returns a string of up to length - 1 bytes read from the file pointed to by handle. If there is no more data to read in the file pointer, then FALSE is returned.

ftell()

Built-in Function: pos = ftell (fid)

Return the position of the file pointer as the number of characters from the beginning of the file specified by file descriptor fid.

fseek()

Built-in Function: fseek (fid, offset) Built-in Function: fseek (fid, offset, origin)

Set the file pointer to the location offset within the file fid.

The pointer is positioned offset characters from the origin, which may be one of the predefined variables SEEK_CUR (current position), SEEK_SET (beginning), or SEEK_END (end of file) or strings "cof", "bof" or "eof". If origin is omitted, SEEK_SET is assumed. offset may be positive, negative, or zero but not all combinations of origin and offset can be realized.

fseek returns 0 on success and -1 on error.

Baskerville answered 27/12, 2015 at 14:59 Comment(0)
V
3

Use PHP function stream_get_meta_data() to find out if the stream you opened is seekable:

$url="http://www.sina.com.cn";
$handle = @fopen($url, "r");

$meta_data = stream_get_meta_data($handle);
var_dump($meta_data['seekable']);

// It prints `bool(false)`

The stream is not seekable. This means the functions fseek(), ftell() and rewind() have unexpected (and probably inconsistent) behaviour.

Vern answered 31/12, 2015 at 8:44 Comment(1)
Adding to this, you should check de return value of fseek(), it should be -1 according to de docs ( ar2.php.net/manual/en/function.fseek.php )Logician

© 2022 - 2024 — McMap. All rights reserved.