Какво правим с файловете, по-големи от 2 GB в PHP?

Скоро ми се наложи да обработвам с 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 обекта

Scripting.FileSystemObject [ http://msdn.microsoft.com/en-us/library/hww8txat(VS.85).aspx ].Неговият метод GetFile връща обект File [http://msdn.microsoft.com/en-us/library/1ft05taf(VS.85).aspx ].Това, което ни върши работа е свойството му Size [http://msdn.microsoft.com/en-us/library/2d66skaf(VS.85).aspx ] – явно НЕ 32 битово число 🙂
В крайна сметка променената функция за големина на файла изглежда така:

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

Your email address will not be published. Required fields are marked *