PHP x86 Как получить размер файла> 2 ГБ без внешней программы? - PullRequest
24 голосов
/ 31 марта 2011

Мне нужно получить размер файла более 2 ГБ. (тестирование на 4,6 ГБ файла). Есть ли способ сделать это без внешней программы?

Текущий статус:

  • filesize(), stat() и fseek() не удается
  • fread() и feof() работает

Существует возможность получить размер файла путем чтения содержимого файла (очень медленно!).

$size = (float) 0;
$chunksize = 1024 * 1024;
while (!feof($fp)) {
    fread($fp, $chunksize);
    $size += (float) $chunksize;
}
return $size;

Я знаю, как получить его на 64-битных платформах (используя fseek($fp, 0, SEEK_END) и ftell()), но мне нужно решение для 32-битной платформы.


Решение: Я начал проект с открытым исходным кодом для этого.

Инструменты для работы с большими файлами

Big File Tools - это набор хаков, необходимых для манипулирования файлами размером более 2 ГБ в PHP (даже в 32-битных системах).

Ответы [ 14 ]

0 голосов
/ 01 апреля 2011

При использовании двойного IEEE (в большинстве систем) размеры файлов ниже ~ 4EB (etabytes = 10 ^ 18 байт) соответствуют точным числам double (и при использовании стандартных арифметических операций не должно быть потери точности).

0 голосов
/ 31 марта 2011

вы можете захотеть добавить некоторые альтернативы к используемой вами функции, например, вызвать системные функции, такие как "dir" / "ls", и получить информацию оттуда.Конечно, они являются предметом безопасности, вещи, которые вы можете проверить и в конечном итоге вернуться к медленному методу только в качестве крайней меры.

0 голосов
/ 31 марта 2011

Если у вас есть FTP-сервер, вы можете использовать fsockopen:

$socket = fsockopen($hostName, 21);
$t = fgets($socket, 128);
fwrite($socket, "USER $myLogin\r\n");
$t = fgets($socket, 128);
fwrite($socket, "PASS $myPass\r\n");
$t = fgets($socket, 128);
fwrite($socket, "SIZE $fileName\r\n");
$t = fgets($socket, 128);
$fileSize=floatval(str_replace("213 ","",$t));
echo $fileSize;
fwrite($socket, "QUIT\r\n");
fclose($socket); 

(встречается как комментарий на странице ftp_size )

0 голосов
/ 31 марта 2011

Один из вариантов - поиск до метки 2 ГБ, а затем чтение длины оттуда ...

function getTrueFileSize($filename) {
    $size = filesize($filename);
    if ($size === false) {
        $fp = fopen($filename, 'r');
        if (!$fp) {
            return false;
        }
        $offset = PHP_INT_MAX - 1;
        $size = (float) $offset;
        if (!fseek($fp, $offset)) {
            return false;
        }
        $chunksize = 8192;
        while (!feof($fp)) {
            $size += strlen(fread($fp, $chunksize));
        }
    } elseif ($size < 0) {
        // Handle overflowed integer...
        $size = sprintf("%u", $size);
    }
    return $size;
}

Таким образом, в основном это ищет наибольшее целое число с положительным знаком в PHP (2 ГБ длябитовая система), а затем выполняет чтение с использованием блоков по 8 КБ (что должно быть справедливым компромиссом для лучшей эффективности памяти по сравнению с эффективностью передачи диска).

Также обратите внимание, что я не добавляю $chunksize к размеру.Причина в том, что fread может фактически возвращать больше или меньше байтов, чем $chunksize, в зависимости от ряда возможностей.Поэтому вместо этого используйте strlen, чтобы определить длину проанализированной строки.

...