Скоро ми се наложи да обработвам с PHP файл с големина около 6 GB. Резултатът от функцията filesize беше много интересен: връща 1.1 GB?!? Оказа се, че това си е документиран БЪГ, за който се споменава, че ще бъде отсранен в 6-та версия. Но до колкото знам има и пач.
Ето и повече инфо за бъг-а:
http://bugs.php.net/bug.php?id=27792
Пачът:
http://news.php.net/php.internals/32767
Едно обяснение и начин за спряване с проблема:
“…The following is from the manual;
Note: Because PHP’s integer type is signed and many platforms use 32bit
integers, filesize() may return unexpected results for files which are
larger than 2GB. For files between 2GB and 4GB in size this can usually
be overcome by using sprintf(“%u”, filesize($file)). “, ноооо – върши работа за файлове до 4GB. А по-големите?
На български и малко по-подробно това звучи така:
В PHP по подразбиране за Integer числата се отделят 32 бита (при 32 битовите платформи!). Това означава, че максималното число, което може да се представи е 2^32=4294967296. За да е по-интересно обаче PHP-торезервира най-старшия бит за знак, което ще рече, че имаме 31 бита т.е. 2^31=2147483648. От тук идва и прословутия лимит от 2 GB.
Трикът, показан по-горе използва sprintf, за да превърне числото със знак в число без знак, което ни дава цели 2 GB предимство т.е. както математиката казва: 2 GB + 2 GB = 4 GB 🙂
Интересна е темата за 64 битова поддръжка в PHP (независимо дали платформата е 32 или 64 битова), но за това се говори едва във версия 6 [http://www.php.net/~derick/meeting-notes.html#add-a-64bit-integer ] !!! До тогава всеки се спасява поединично [http://www.gerd-riesselmann.net/archives/2006/01/a-64-bit-integer-for-php ]
Интересна заобиколка е и използването на COM обекта
function knj_filesize($file){
if (file_exists($file)){
$fsobj = new COM(“Scripting.FileSystemObject”);
$file = $fsobj->GetFile($file);
$var = ($file->Size) + 1 – 1;
return $var;
}else{
echo “File does not exist.\n”;
return false;
}
}
Източник: http://bg.php.net/manual/bg/function.filesize.php#68209
Leave a Reply