Question

I'm using a simple unzip function (as seen below) for my files so I don't have to unzip files manually before they are processed further.

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

The problem is that if the gzip file is large (e.g. 50mb) the unzipping takes a large amount of ram to process.

The question: can I parse a gzipped file in chunks and still get the correct result? Or is there a better other way to handle the issue of extracting large gzip files (even if it takes a few seconds more)?

Was it helpful?

Solution

gzfile() is a convenience method that calls gzopen, gzread, and gzclose.

So, yes, you can manually do the gzopen and gzread the file in chunks.

This will uncompress the file in 4kB chunks:

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);
}

OTHER TIPS

try with

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

$length parameter is optional.

If you are on a Linux host, have the required privilegies to run commands, and the gzip command is installed, you could try calling it with something like shell_exec

SOmething a bit like this, I guess, would do :

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

This way, the file wouldn't be unzip by PHP.


As a sidenote :

  • Take care where the command is run from (ot use a swith to tell "decompress to that directory")
  • You might want to take a look at escapeshellarg too ;-)

As maliayas mentioned, it may lead to a bug. I experienced an unexpected fall out of the while loop, but the gz file has been decompressed successfully. The whole code looks like this and works better for me:

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; 
} 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top