zip_read()
Функция zip_read() в PHP читает следующую запись из открытого zip-архива. Устарела в PHP 8.0 — используйте ZipArchive.
⚠️ Уведомление об устаревшем API: Функция
zip_read()и связанные с ней процедурные функции для работы с zip были удалены в PHP 8.0. Они требуют расширенияext-zipPECL и доступны только в PHP 7.4 и более ранних версиях. Для современных приложений на PHP рекомендуется классZipArchive.
Функция zip_read() читает следующую запись (отдельный файл или запись каталога) из открытого zip-архива. Она является частью устаревшего процедурного API PHP для работы с zip, в котором архив обходится по одной записи за раз: открываете архив с помощью zip_open(), последовательно вызываете zip_read() для перехода к следующим записям, а затем закрываете его с помощью zip_close().
Каждый успешный вызов возвращает ресурс записи zip — дескриптор, который передаётся функциям zip_entry_* для проверки или чтения этой записи. Когда записей больше нет, zip_read() возвращает false, что и завершает цикл. При ошибке вместо этого возвращается числовой код ошибки.
Синтаксис
Синтаксис функции zip_read() выглядит следующим образом:
Синтаксис функции zip_read() в PHP
resource|int|false zip_read(resource $zip)$zip — ресурс архива, возвращённый функцией zip_open(). Возвращаемое значение — одно из следующих:
- ресурс записи zip — есть запись для обработки;
false— достигнут конец архива;- целочисленный код ошибки — при чтении архива что-то пошло не так.
Зачем использовать цикл с zip_read()?
Процедурный API представляет собой курсор с односторонним движением вперёд: вызова «получить все записи» не существует. Вы читаете одну запись, выполняете с ней какие-либо действия (получаете её имя и размеры или извлекаете содержимое), а затем запрашиваете следующую. Это позволяет снизить использование памяти, поскольку в области видимости одновременно находится только одна запись, но также означает, что нельзя перейти к произвольной записи — необходимо обходить архив с самого начала.
Примеры использования
Пример: перечисление записей в zip-архиве
Этот цикл открывает архив и выводит метаданные для каждой содержащейся в нём записи:
Чтение записей zip-архива в PHP
$zip = zip_open("example.zip");
if (!is_resource($zip)) {
throw new RuntimeException("Failed to open zip archive (error code: $zip)");
}
while ($zip_entry = zip_read($zip)) {
echo "Name: " . zip_entry_name($zip_entry) . "\n";
echo "Compressed Size: " . zip_entry_compressedsize($zip_entry) . "\n";
echo "Uncompressed Size: " . zip_entry_filesize($zip_entry) . "\n";
}
zip_close($zip);Код открывает example.zip с помощью zip_open(), а затем выполняет цикл, пока zip_read() продолжает возвращать ресурсы записей. Для каждой записи выводится имя с помощью zip_entry_name(), размер в сжатом виде с помощью zip_entry_compressedsize() и исходный размер с помощью zip_entry_filesize(). Наконец, zip_close() освобождает архив.
Пример: чтение содержимого записи
zip_read() только устанавливает текущую позицию на запись; чтобы прочитать реальные байты, необходимо открыть запись с помощью zip_entry_open() и получить данные с помощью zip_entry_read():
$zip = zip_open("example.zip");
if (is_resource($zip)) {
while ($entry = zip_read($zip)) {
if (zip_entry_open($zip, $entry, "r")) {
$contents = zip_entry_read($entry, zip_entry_filesize($entry));
echo zip_entry_name($entry) . ":\n" . $contents . "\n";
zip_entry_close($entry);
}
}
zip_close($zip);
}Распространённые ошибки
- Истинность значения в цикле.
while ($entry = zip_read($zip))работает, потому что корректный ресурс является истинным, аfalseзавершает цикл. Однако при ошибке также возвращается целочисленный код — проверяйтеis_resource($zip)послеzip_open(), чтобы никогда не итерировать по сломанному дескриптору. - Движение только вперёд. Перемотки нет. Чтобы обработать архив повторно, откройте его заново с помощью
zip_open(). - Удалено в PHP 8. Эти функции были удалены в PHP 8.0. Код, который должен работать на современном PHP, следует переписать с использованием объектно-ориентированного класса
ZipArchive.
Современная альтернатива: ZipArchive
В PHP 8 и более поздних версиях для обхода архива используйте класс ZipArchive. Он также предоставляет произвольный доступ по индексу, что невозможно с zip_read():
$zip = new ZipArchive();
if ($zip->open("example.zip") === true) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$stat = $zip->statIndex($i);
echo "Name: {$stat['name']}\n";
echo "Compressed Size: {$stat['comp_size']}\n";
echo "Uncompressed Size: {$stat['size']}\n";
}
$zip->close();
}Смотрите обзор расширения PHP Zip для полного описания API ZipArchive.
Заключение
zip_read() перемещает однонаправленный курсор по записям zip-архива, открытого с помощью zip_open(), каждый раз возвращая ресурс записи и false в конце. Это основа устаревшего процедурного цикла чтения zip в паре с функциями zip_entry_* для проверки и извлечения каждой записи. Поскольку этот API был удалён в PHP 8.0, для кода, ориентированного на актуальные версии PHP, предпочтительно использовать ZipArchive.