2

I would like to search files for a given string within a zipped folder.

I can currently get a list of my zipped files doing the following:

$zip = new ZipArchive;
$res = $zip->open("./test.zip");
var_dump($res);
for( $i = 0; $i < $zip->numFiles; $i++ ){
    $stat = $zip->statIndex( $i );
    var_dump($stat['name']);
}
$zip->close();

I have been reviewing the solutions found here. The only solution that seems to touch on what I need is both procedural and has a comment noting the following:

zip_entry_read reads only 1024 bytes from file by default.. so contents is not full contents of the file, but only first 1024 bytes

Is there a (OOP) way to search the entirety of my entries for a string before I choose to unzip my folder? Additionally, if I wanted to display the full contents of a zipped file would it need to be unzipped first? Lastly, if the full contents cannot be displayed without unzipping, is there a way to extract a single file from a zipped folder?

Newb 4 You BB
  • 1,205
  • 1
  • 11
  • 30

2 Answers2

2

You can use ZipArchive::getFromName() or ZipArchive::getFromIndex() to read the zipped file contents.

$zip = new ZipArchive;
$res = $zip->open("./test.zip");
for( $i = 0; $i < $zip->numFiles; $i++ ){
    var_dump($zip->getFromIndex($i));
}
$zip->close();
vhu
  • 12,244
  • 11
  • 38
  • 48
1

If you want to search the contents of each file, decompression will have to happen, no matter what. It might not happen in a disk-based format, but it will happen somewhere, such as in memory. Just FYI, that's how compressed files just work.

I would abandon the OOP-based ZipArchive class, it is hit-or-miss for whether or not a method exists that corresponds to the function-based ones.

If you want to search the contents of a file, you'll need to pass the number of bytes as the second parameter to zip_entry_read() for the corresponding entry. To get the number of bytes, call zip_entry_filesize

$zip = zip_open('./file.zip');
while ($entry = zip_read($zip)) {
    // This is the uncompressed size
    $true_size = zip_entry_filesize($entry);

    // Read everything
    $true_entry = zip_entry_read($entry, $true_size);

    $idx = mb_strpos($true_entry, 'string-you-are-looking-for');
    if ($idx) {
        echo 'Found!';
    }
}

The variable $true_entry inside the loop will be an individual file and you can get its name using zip_entry_name.

Chris Haas
  • 53,986
  • 12
  • 141
  • 274