Nathan
Nathan

Reputation: 1371

PHP working with huge numbers

I am writing an application that can stream videos. It requires the filesize of the video, so I use this code:

$filesize = sprintf("%u", filesize($file));

However, when streaming a six gig movie, it fails.

Is is possible to get a bigger interger value in PHP? I don't care if I have to use third party libraries, if it is slow, all I care about is that it can get the filesize properly.

FYI, $filesize is currently 3017575487 which is really really really really far from 6000000000, which is roughly correct.

I am running PHP on a 64 bit operating system.

Thanks for any suggestions!

Upvotes: 0

Views: 109

Answers (2)

Alexander O'Mara
Alexander O'Mara

Reputation: 60517

The issue here is two-fold.

Problem 1


The filesize function returns a signed integer, with a maximum value of PHP_INT_MAX. On 32-bit PHP, this value is 2147483647 or about 2GB. On 64-bit PHP can you go higher, up to 9223372036854775807. Based on the comments from the PHP filesize page, I created a function that will use a fseek loop to find the size of the file, and return it as a float, which can count higher that a 32-bit unisgned integer.

function filesize_float($filename)
{
    $f = fopen($filename, 'r');
    $p = 0;
    $b = 1073741824;
    fseek($f, 0, SEEK_SET);
    while($b > 1)
    {
        fseek($f, $b, SEEK_CUR);
        if(fgetc($f) === false)
        {
            fseek($f, -$b, SEEK_CUR);
            $b = (int)($b / 2);
        }
        else
        {
            fseek($f, -1, SEEK_CUR);
            $p += $b;
        }
    }
    while(fgetc($f) !== false)
    {
        ++$p;
    }
    fclose($f);
    return $p;
}

To get the file size of the file as a float using the above function, you would call it like this.

$filesize = filesize_float($file);

Problem 2


Using %u in the sprintf function will cause it to interpret the argument as an unsigned integer, thus limiting the maximum possible value to 4294967295 on 32-bit PHP, before overflowing. Therefore, if we were to do the following, it would return the wrong number.

sprintf("%u", filesize_float($file));

You could interpret the value as a float using %F, using the following, but it will result in trailing decimals.

sprintf("%F", filesize_float($file));

For example, the above will return something like 6442450944.000000, rather than 6442450944.

A workaround would be to have sprintf interpret the float as a string, and let PHP cast the float to a string.

$filesize = sprintf("%s", filesize_float($file));

This will set $filesize to the value of something like 6442450944, without trailing decimals.


The Final Solution


If you add the filesize_float function above to your code, you can simply use the following line of code to read the actual file size into the sprintf statement.

$filesize = sprintf("%s", filesize_float($file));

Upvotes: 1

prashant thakre
prashant thakre

Reputation: 5147

As per PHP docuemnation for 64 bit platforms, this seems quite reliable for getting the filesize of files > 4GB

<?php 
$a = fopen($filename, 'r'); 
fseek($a, 0, SEEK_END); 
$filesize = ftell($a); 
fclose($a); 
?>

Upvotes: 0

Related Questions