Question:
I was reading the PHP documentation and noticed this information:
Note: Because PHP's integer type is signed and many platforms use 32bit integers, some filesystem functions may return unexpected results for files which are larger than 2GB.
When accessing the documentation in Portuguese I noticed this:
Note: As PHP integer type is signed and many platforms use 32-bit integers, filesize() may return unexpected results for files that are larger than 2Gb. For files between 2Gb and 4Gb you can solve this problem using sprintf ("%u", filesize($file)).
They pass a tip on the use of sprintf
, however I found this question:
- PHP x86 How to get filesize of >2GB file without external program? (they even built a class for such a service https://github.com/jkuchar/BigFileTools )
Apparently they tried various methods. I don't know if it was a contributor to the Portuguese documentation who added this code:
sprintf("%u", filesize($file))
What I would like to know is if he has any problems (since it seems that only the Portuguese documentation people thought about this). For example:
- Does it fail in any given situation?
- Is it not accurate as to the actual weight of the file?
- Or does the code really work to convert the integer weight to a numeric string?
Answer:
It appears that the problem is due to the flagging PHP itself imposes on integer types, and many platforms use 32-bit flags, which is why filesize() sometimes returns unexpected results for files larger than 2GB .
As for the explanation of why this expression is more suitable, it is a bit tricky to answer, since many users have tried in various ways to write their own and even more complex methods to obtain the real size of a file.
It prints the result of filesize as UNSIGNED INT so it can be until 4GB. The reason is, SIGNED INT runs until 2GB and flips to -2GB watch following:
Translation: This prints the output of _"filesize" as "unsigned integer" , so it can be up to 4GB. It happens because, "signed integers" run up to 2GB and flip to -2GB, see:
file<2GB = SIGNED: 1048576512 UNSIGNED: 1048576512
file>2GB = SIGNED: -2100140103 UNSIGNED: 2194827193
file>4GB = SIGNED: -100662784 UNSIGNED: 4194304512
This text quoted above was taken from any PHP directory, in it the user explains why the function. But it does not say if it is the most suitable or not.
In my view, it is very likely that this expression is being used, because it returns negative values for files between 2GB and 4GB , which can still be corrected with some calculation, and returns a definitive and incorrigible value for files above 4GB . In fact, it was rather alarming that the example was only in the documentation note in Portuguese, but the example already existed in the contribution notes.
In the PHP page usually the examples we find there are the simplest, that doesn't mean that it is the only way to get the real size of a file. This will likely require some testing on your part, as you don't find much information about why you use sprintf .
Does it fail in any given situation?
Some users have reported that there have been glitches on some systems based on the x86 architecture, and some problems have been reported on x64 systems, so it is very likely that there are still some bugs. Even if it fails, it will return an E_WARNING
or simply FALSE
.
Is it not accurate as to the actual weight of the file?
Precision is good, returns actual size in bytes .
Or does the code really work to convert the integer weight to a numeric string?
Yes, it works, this was the return I got in the last result:
$file = "ficheiro.zip";
var_dump(sprintf("%u", filesize($file)));
Retorno: string(4) "5209" (5.08KB)
Retorno: string(10) "2092964971" (1.94GB)
There are several examples available on how to get the actual size of files for the most diverse platforms, some are even shell
based, just look for the one that suits you best. If you need more details, I think the only solution will be to do isolated tests, and go deeper in the search.
Good luck.