When handling ZIP files in PHP, the zip_read() function is a common method for reading ZIP file entries. However, many developers encounter the problem of empty directories being lost when extracting ZIP files that contain them. This happens because empty directories do not contain files, and zip_read() by default only iterates over file entries while ignoring directory entries, resulting in empty directories not being properly created.
This article will, with example code, detail how to use the zip_read() function to correctly identify and extract empty directories, preventing them from being lost and ensuring the extracted file structure is complete.
ZIP file entries include both files and directories, with directory entries typically ending with a /. If the entry name returned by zip_read() ends with a /, it indicates a directory. During normal extraction, if only the directories corresponding to files are created but empty directory entries are not processed, empty directories will be ignored.
Below is an example based on PHP’s native ZIP functions, demonstrating how to read a ZIP file, distinguish between files and directories, and correctly create empty directories.
<?php
$zipPath = 'archive.zip'; // Path to the ZIP file
$extractTo = 'output/'; // Extraction target directory
<p>$zip = zip_open($zipPath);<br>
if (!is_resource($zip)) {<br>
die("Unable to open ZIP file\n");<br>
}</p>
<p>while ($entry = zip_read($zip)) {<br>
$entryName = zip_entry_name($entry);</p>
if (substr($entryName, -1) === '/') {
// Create empty directory
$dirPath = $extractTo . $entryName;
if (!is_dir($dirPath)) {
mkdir($dirPath, 0755, true);
echo "Created empty directory: $dirPath\n";
}
} else {
// File entry, first ensure directory exists
$filePath = $extractTo . $entryName;
$dir = dirname($filePath);
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
// Read file content and write it
if (zip_entry_open($zip, $entry)) {
$fp = fopen($filePath, 'w');
while ($data = zip_entry_read($entry, 1024)) {
fwrite($fp, $data);
}
fclose($fp);
zip_entry_close($entry);
echo "Extracted file: $filePath\n";
}
}
}
zip_close($zip);
?>
Identify directory entries: Use zip_entry_name() to get the entry name; directory entries usually end with a /.
Create empty directories: Directly create the corresponding directory when a directory entry is encountered.
Create files and their parent directories: For file entries, ensure the parent directory exists before writing the file content.
Permissions and recursive creation: Set the third parameter of mkdir() to true to recursively create multi-level directories.
For more information about PHP Zip functions, please refer to the official manual:
Related Tags:
mysqli