Распаковать большие файлы с помощью 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;
}