Распаковать большие файлы с помощью gzip в PHP

Я использую несложную функцию распаковки (как показано ниже) для своих файлов, поэтому мне не нужно разархивировать файлы вручную, прежде чем они будут обработаны дальше.

function uncompress($srcName, $dstName) {
    $string = implode("", gzfile($srcName));
    $fp = fopen($dstName, "w");
    fwrite($fp, $string, strlen($string));
    fclose($fp);
} 

Проблема заключается в том, что если файл gzip большой (например, 50 МБ), распаковка занимает большое количество оперативной памяти для обработки.

Вопрос: могу ли я разобрать gzip файл в кусках и по-прежнему получить правильный результат? Или есть лучший другой способ справиться с проблемой извлечения больших файлов gzip (даже если это занимает несколько секунд)?

Ответ 1

gzfile() - метод удобства, который вызывает gzopen, gzread и gzclose.

Итак, да, вы можете вручную сделать gzopen и gzread файл в кусках.

Это приведет к распаковке файла в 4kB фрагментах:

function uncompress($srcName, $dstName) {
    $sfp = gzopen($srcName, "rb");
    $fp = fopen($dstName, "w");

    while (!gzeof($sfp)) {
        $string = gzread($sfp, 4096);
        fwrite($fp, $string, strlen($string));
    }
    gzclose($sfp);
    fclose($fp);
}

Ответ 2

попробуйте

function uncompress($srcName, $dstName) {
    $fp = fopen($dstName, "w");
    fwrite($fp, implode("", gzfile($srcName)));
    fclose($fp);
}

$параметр длины необязателен.

Ответ 3

Если вы находитесь на хосте Linux, у вас есть необходимые привилегии для запуска команд, а команда gzip установлена, вы можете попробовать называть ее чем-то вроде shell_exec

Что-то вроде этого, я думаю, будет делать:

shell_exec('gzip -d your_file.gz');

Таким образом, файл не будет распаковываться с помощью PHP.


В качестве опоры:

  • Позаботьтесь о том, где выполняется команда (ot используйте swith, чтобы сообщить "распаковать в этот каталог" )
  • Возможно, вы захотите взглянуть на escapeshellarg, -)

Ответ 4

Как упоминалось maliayas, это может привести к ошибке. Я испытал неожиданное падение из цикла while, но файл gz был успешно распакован. Весь код выглядит так и работает лучше для меня:

function gzDecompressFile($srcName, $dstName) { 
    $error = false; 

    if( $file = gzopen($srcName, 'rb') ) { // open gz file

        $out_file = fopen($dstName, 'wb'); // open destination file

        while (($string = gzread($file, 4096)) != '') { // read 4kb at a time   
            if( !fwrite($out_file, $string) ) { // check if writing was successful
                 $error = true;
            }   
        }

        // close files
        fclose($out_file);
        gzclose($file);     

    } else {
        $error = true;
    }

    if ($error)
        return false; 
    else
        return true; 
}