Zip read: примеры (PHP)

Работа с zip_read в PHP: примеры и аналоги
Раздел: Архивация
zip_read(resource zip): resource|false
Описание функции zip_read

Функция zip_read() в PHP является частью устаревшего модуля Zip (Zip Functions). Она использовалась для последовательного чтения содержимого ZIP-архива. Эта функция читает следующую запись в открытом ZIP-архиве.

Назначение и применение

Функция применялась для итерации по элементам архива без предварительного получения полного списка. Ее использовали для обработки больших архивов, когда загрузка всей структуры в память была нежелательна.

Аргументы функции

Функция принимает один обязательный параметр:

  • $zip (ресурс) - ресурс ZIP-архива, полученный с помощью функции zip_open().

Возвращает ресурс записи ZIP в случае успеха или false при завершении чтения или возникновении ошибки.

Примечание об устаревании

Важно отметить, что модуль Zip, включая функцию zip_read(), устарел и удален в PHP 8.0.0. Вместо него рекомендуется использовать объектно-ориентированный класс ZipArchive.

Примеры использования
Базовый пример чтения архива

Следующий код демонстрирует чтение всех элементов в ZIP-архиве с помощью устаревших функций.

<?php
$zip = zip_open('example.zip');
if ($zip) {
    while ($zip_entry = zip_read($zip)) {
        $name = zip_entry_name($zip_entry);
        echo "Найден элемент: $name<br>";
    }
    zip_close($zip);
}
?>
Найден элемент: document.txt
Найден элемент: images/photo.jpg
Найден элемент: data/config.ini
Чтение содержимого файла из архива

Пример извлечения и вывода содержимого текстового файла.

<?php
$zip = zip_open('archive.zip');
if ($zip) {
    while ($entry = zip_read($zip)) {
        $entry_name = zip_entry_name($entry);
        if (zip_entry_open($zip, $entry)) {
            if (str_ends_with($entry_name, '.txt')) {
                $contents = zip_entry_read($entry, zip_entry_filesize($entry));
                echo "Содержимое $entry_name:<br>$contents<br>";
            }
            zip_entry_close($entry);
        }
    }
    zip_close($zip);
}
?>
Содержимое notes.txt:
Текст заметки.
Вторая строка.
Альтернативы в PHP

Основной современной альтернативой является класс ZipArchive, входящий в стандартную библиотеку PHP.

Класс ZipArchive

Объектно-ориентированный интерфейс предоставляет больше возможностей и лучше интегрирован с современным PHP.

<?php
$zip = new ZipArchive();
if ($zip->open('archive.zip') === TRUE) {
    for ($i = 0; $i < $zip->numFiles; $i++) {
        $name = $zip->getNameIndex($i);
        echo "Элемент: $name<br>";
    }
    $zip->close();
}
?>
Рекомендации по выбору

Класс ZipArchive следует использовать во всех новых проектах, так как он поддерживается, имеет более богатый функционал (добавление, удаление, изменение элементов) и безопаснее. Устаревшие функции zip_* были полностью удалены в PHP 8.0.0.

Аналоги в других языках

Zip read в Python

В Python используется модуль zipfile. Чтение архива происходит итеративно или через получение списка.

import zipfile
with zipfile.ZipFile('archive.zip', 'r') as zf:
    for item in zf.infolist():
        print(f'Элемент: {item.filename}')
        # Чтение содержимого
        with zf.open(item) as f:
            content = f.read()
            # Обработка содержимого
JavaScript (Node.js)

В Node.js популярна библиотека adm-zip или использование встроенного модуля yauzl для потокового чтения.

const AdmZip = require('adm-zip');
const zip = new AdmZip('archive.zip');
const entries = zip.getEntries();
entries.forEach(entry => {
    console.log(`Элемент: ${entry.entryName}`);
    const content = entry.getData().toString('utf8');
});

Zip read в Java

В Java используется java.util.zip.ZipFile.

import java.util.zip.ZipFile;
import java.util.Enumeration;
ZipFile zipFile = new ZipFile('archive.zip');
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
    ZipEntry entry = entries.nextElement();
    System.out.println('Элемент: ' + entry.getName());
}

Основное отличие от старого PHP подхода — объектная модель и часто более развитое API.

Типичные ошибки
Использование в PHP 8 и выше

Самая распространенная ошибка — попытка использовать устаревшую функцию в PHP 8, где она была удалена.

<?php
// Этот код вызовет фатальную ошибку в PHP 8.0.0+
$zip = zip_open('file.zip');
?>
Fatal error: Uncaught Error: Call to undefined function zip_open()
Отсутствие проверки ресурса

Невыполнение проверки успешности открытия архива вело к ошибкам.

<?php
$zip = zip_open('missing.zip');
$entry = zip_read($zip); // Предупреждение, если $zip не ресурс
?>
Warning: zip_read() expects parameter 1 to be resource, bool given
Незакрытие ресурса

Забывали закрывать архив, что могло приводить к утечкам ресурсов.

<?php
$zip = zip_open('large.zip');
// ... чтение архива
// zip_close($zip); не вызвана
?>
Изменения в версиях PHP

Функции модуля Zip претерпели значительные изменения.

PHP 5.x - 7.x

Модуль был доступен, но считался устаревшим. Рекомендовался переход на ZipArchive.

PHP 8.0.0

Весь старый модуль Zip, включая функции zip_open(), zip_read(), zip_entry_name() и другие, был полностью удален из ядра PHP. Попытка вызова вызывает фатальную ошибку.

Альтернативный путь

Расширение zip, предоставляющее класс ZipArchive, осталось и является стандартным способом работы с ZIP.

Расширенные примеры (исторические)

Приведенные примеры актуальны только для PHP версий ниже 8.0.

Фильтрация по типу файлов при чтении

Чтение только PHP файлов из архива с проверкой расширения.

Пример php
<?php
$zip = zip_open('source.zip');
if (is_resource($zip)) {
    while ($entry = zip_read($zip)) {
        $name = zip_entry_name($entry);
        if (preg_match('/\.php$/', $name)) {
            echo "PHP файл: $name<br>";
            if (zip_entry_open($zip, $entry, 'r')) {
                $size = zip_entry_filesize($entry);
                $content = zip_entry_read($entry, $size);
                // Анализ содержимого
                if (strpos($content, 'function') !== false) {
                    echo "Содержит функции.<br>";
                }
                zip_entry_close($entry);
            }
        }
    }
    zip_close($zip);
}
?>
Извлечение структуры каталогов

Анализ пути к элементу для построения дерева каталогов.

Пример php
<?php
$zip = zip_open('project.zip');
$structure = [];
if ($zip) {
    while ($entry = zip_read($zip)) {
        $path = zip_entry_name($entry);
        $parts = explode('/', $path);
        // Построение вложенного массива структуры
        $current = &$structure;
        foreach ($parts as $part) {
            if (!isset($current[$part])) {
                $current[$part] = [];
            }
            $current = &$current[$part];
        }
    }
    zip_close($zip);
    echo 'Структура архива:<br>';
    print_r($structure);
}
?>
Чтение с обработкой больших файлов по частям

Для больших файлов внутри архива чтение происходило частями.

Пример php
<?php
$zip = zip_open('big.zip');
if ($zip) {
    while ($entry = zip_read($zip)) {
        if (zip_entry_open($zip, $entry)) {
            $chunkSize = 1024; // 1KB
            while ($data = zip_entry_read($entry, $chunkSize)) {
                // Обработка каждого чанка данных
                // Например, поиск строки
                if (strpos($data, 'ERROR') !== false) {
                    echo 'Найдена ошибка в чанке.<br>';
                }
            }
            zip_entry_close($entry);
        }
    }
    zip_close($zip);
}
?>

PHP zip_read function comments

En
Zip read Read next entry in a ZIP file archive