PHP: полный мануал с примерами, функциями и ООП
Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Дерево руководства
Глава 105 · От основ к практике
Bzip2: сжатые строки, файлы .bz2 и безопасное чтение выгрузки
Полная ветка Bzip2: установка, все 10 функций, потоки, ошибки и ограничения импорта.
Отчёт меньше при передаче, прежние данные после распаковки
Из stock.csv.bz2 возвращаем строки остатков
Bzip2 меняет представление последовательности байтов. Разбор товаров начинается после корректной распаковки.
- 1CSV: SKU-7;2↓
Исходные данные поставщика описывают товар и остаток.
- 2Bzip2-поток↓
Сжатые байты сохраняют или передают без текстовых преобразований.
- 3Распаковка порциями↓
bzread отдаёт куски, которые не обязаны совпадать со строками CSV; проверяем bzerror и лимиты.
- 4Разбор и проверка CSV
После завершённого потока проверяем поля и только затем меняем данные приложения.
Непустой результат не доказывает целостность усечённого входа. bzdecompress может требовать много памяти; .tar.bz2 после распаковки всё ещё содержит TAR-контейнер.
Поставщик отдаёт выгрузку остатков в CSV, но передаёт файл stock.csv.bz2. Сначала нужно вернуть исходный текст, затем разбирать строки CSV. Bzip2 решает первый шаг: сжимает последовательность байтов без потери содержимого. Он не понимает товары, столбцы и SQL.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
- Текст: SKU-7;2
- Сжатие → двоичные байты Bzip2
- Передача или сохранение этих байтов
- Распаковка → снова SKU-7;2; затем разбор CSV
<?php
$packed = bzcompress('SKU-7;2');
$text = bzdecompress($packed);
echo $text, "\n";
Ожидаемый результат
SKU-7;2
Опыт использует заведомо исправные короткие данные и установленное расширение. Файл не создаётся: обе строки находятся в памяти. Следующие разделы добавляют обработку отказа и работу с файлом.
Аналогия — компактная упаковка одного рулона данных. Она не является паролем или шифрованием и не даёт права доверять содержимому после распаковки. Сжатие не обязано уменьшать короткие или уже сжатые данные.
Выбрать строку, поток или архив
| Задача | Инструмент | Граница |
|---|---|---|
| Короткая строка уже в памяти | bzcompress() / bzdecompress() | Вход и весь выход находятся в памяти; у bzdecompress нет параметра максимума результата. |
| Один большой .csv.bz2 | bzopen() → bzread() → bzclose() | Читаем порции распакованных байтов и проверяем ошибки. Размер порции не равен строке CSV. |
| Записать отчёт порциями | bzopen() → bzwrite() → bzclose() | Передаём несжатые строки; w обнуляет прежний файл. |
| Несколько файлов в .tar.bz2 | Bzip2 сжимает TAR-контейнер; разбор TAR — отдельный этап | Распакованные байты здесь будут TAR, а не сразу CSV. |
| Файл .zip или .gz | Нужен обработчик соответствующего формата | Имена расширений не подтверждают содержимое. Установка ZIP не включает автоматически bz2. |
Bzip2 не является универсальным транспортным форматом JSON/HTTP. При интеграции согласуйте с другой стороной точные байты и алгоритм; Base64 только превращает бинарные данные в текст и увеличивает размер. Не применяйте bzcompress к уже сжатому результату без специальной причины.
Установка, libbzip2 и проверка нужного PHP
В PHP это расширение bz2, а внешняя библиотека — libbzip2 версии не ниже 1.0.x. Поддержка не включается автоматически во всех сборках. При сборке PHP используют --with-bz2[=DIR]. В готовой системе выбирают пакет своего дистрибутива/версии PHP; на Windows — совместимую php_bz2.dll из соответствующей сборки, с совпадающими версией, архитектурой и TS/NTS.
В php.ini запись extension=bz2 подключает доступную библиотеку. CLI и сервер могут читать разные ini: команды php --ini, php -m, php --ri bz2 относятся к тому php, который найден в PATH. Composer проверяет окружение своего CLI, а не веб-страницу. После настройки веб-процессы перезапускают и проверяют тем же способом внутри нужного SAPI.
- Найти конкретный PHP и его ini
- extension_loaded("bz2") → включено ли расширение в этом процессе
- function_exists("bzopen") → доступен ли нужный API
- Только после этого выполнять примеры
<?php
var_dump(extension_loaded('bz2'));
var_dump(function_exists('bzopen'));
var_dump(in_array('compress.bzip2', stream_get_wrappers(), true));
Ожидаемый результат
bool(true)
bool(true)
bool(true)
Этот результат относится к PHP с явно подключённым bz2. in_array ищет строку среди имён обёрток; третий аргумент true включает строгое сравнение.
У расширения нет собственных php.ini-директив и экспортируемых PHP-констант. Обёртка compress.bzip2:// и фильтры bzip2.compress/bzip2.decompress предоставляют отдельные потоковые входы; их наличие не меняет контракт функций ниже. Что такое обёртка и поток. Динамическое подключение через dl в обработчике запроса здесь не требуется.
Проверка этой главы: PHP 8.5.11, libbzip2 1.0.8; DLL включалась только для тестового процесса через -d extension=bz2. Основные примеры подходят для PHP 8.2+, а тест новых ошибок bzcompress отдельно помечен 8.5+.
Открыть, прочитать или записать, завершить
bzopen возвращает ресурс — временный указатель на открытый поток, либо false при отказе. Это не содержимое файла. if (...) { ... } выбирает ветку; throw new RuntimeException(...) останавливает обычный путь с описанием ошибки. В try { ... } finally { bzclose($handle); } блок finally освобождает поток даже при исключении, но не подавляет ошибку. Потоки и позиция чтения; Обработка ошибки.
- bzopen("report.bz2", "w") выдаёт указатель на поток
- bzwrite передаёт обычные порции текста
- bzclose завершает и закрывает поток
- Новый bzopen(..., "r") создаёт независимого читателя
У читающего ресурса есть позиция: каждое чтение продвигает её. У пишущего ресурса есть состояние компрессора: пока поток не завершён, файл нельзя считать готовой выгрузкой. bzflush() — исторический no-op; это не публикация готовых данных. bzclose() не удаляет файл, а освобождает ресурс.
Старые руководства называют возвращаемое значение указателем файла Bzip2. В PHP это resource, в текущей реализации — поток. Нельзя создавать его через new или передавать вместо него имя файла в bzread. Если bzopen получает уже открытый совместимый файловый поток, закрытие обёртки закрывает и исходный ресурс; это показано в примере владения ресурсом.
Три разных отказа: открыть путь, разобрать Bzip2, проверить документ
| Этап | Признак | Действие |
|---|---|---|
| Открытие пути | bzopen вернул false или диагностировал неверный аргумент | Не вызывать bzerror(false); проверить путь, права, режим и исходный поток. |
| Распаковка | bzread вернул false либо bzerror сообщает ошибку | Сохранить техническую причину, закрыть ресурс, отвергнуть документ. |
| Смысл выгрузки | Bzip2 корректен, но нет нужной шапки/поля/типа/подписи источника | Проверить схему и договор источника до бизнес-изменений. |
Числа ниже пришли из libbzip2. Они не объявлены в PHP как константы BZ_*. Диагностические функции возвращают код/строку для открытого ресурса; bzcompress и bzdecompress могут вернуть число непосредственно. Не каждый код достижим каждым PHP-вызовом.
| Код / имя в библиотеке | Смысл |
|---|---|
| 0 — BZ_OK | Ошибка не зарегистрирована. |
| −1 — BZ_SEQUENCE_ERROR | Неподходящая последовательность операций/состояние. |
| −2 — BZ_PARAM_ERROR | Некорректный параметр низкоуровневого API; часть случаев PHP перехватывает исключениями. |
| −3 — BZ_MEM_ERROR | Библиотеке не хватило рабочей памяти. |
| −4 — BZ_DATA_ERROR | Повреждены данные или контрольная сумма. |
| −5 — BZ_DATA_ERROR_MAGIC | Начало потока не соответствует Bzip2. |
| −6 — BZ_IO_ERROR | Ошибка ввода/вывода. |
| −7 — BZ_UNEXPECTED_EOF | Файл закончился раньше завершения сжатого потока. |
| −8 — BZ_OUTBUFF_FULL | Недостаточно выходного буфера у соответствующего библиотечного API. |
| −9 — BZ_CONFIG_ERROR | Несовместимая конфигурация библиотеки. |
В низкоуровневой библиотеке существуют и положительные состояния выполнения 1…4. Не переносите её протокол напрямую на PHP: например, в проверенном корректном завершении bzerror сообщает errno=0/errstr=OK, а не обязательное число 4.
Функция импорта: сначала проверить весь ограниченный документ
Теперь вход — путь к одному сжатому CSV. Мы хотим получить текст, только если чтение не выявило ошибки и распакованный объём не превысил 12 000 байт. Это компактная демонстрация политики «всё или отказ», поэтому хранить весь результат здесь допустимо. Для большого импорта выход складывают в служебный файл или промежуточное хранилище; бизнес-изменения подтверждают после проверки документа.
function readReport($path, $limit) объявляет операцию с двумя входами; return $text возвращает её результат. .= дописывает строку, while повторяет чтение, break завершает цикл. $error['errno'] — поле массива. Вызвавшая сторона ловит RuntimeException и не получает частичный отчёт. Параметры и return; Ключи массива.
- Открыть путь → ресурс
- Читать порцию → проверить bzerror и суммарный предел
- Только после конца без ошибки вернуть весь текст
- Проверить CSV-схему; затем отдельный этап базы
<?php
function readReport($path, $limit) {
if (!is_int($limit) || $limit < 1) {
throw new InvalidArgumentException('Неверный лимит');
}
$handle = bzopen($path, 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
$text = '';
try {
while (true) {
$chunk = bzread($handle, 4096);
$error = bzerror($handle);
if ($chunk === false || $error['errno'] !== 0) {
throw new RuntimeException('Повреждённый Bzip2');
}
if ($chunk === '') { break; }
if (strlen($chunk) > $limit - strlen($text)) {
throw new RuntimeException('Превышен лимит');
}
$text .= $chunk;
}
return $text;
} finally { bzclose($handle); }
}
file_put_contents('valid.bz2', bzcompress("id;qty\n7;2\n"));
echo readReport('valid.bz2', 12000);
$large = bzcompress(str_repeat('A', 10000));
file_put_contents('cut.bz2', substr($large, 0, -10));
file_put_contents('large.bz2', $large);
foreach (['cut.bz2', 'large.bz2'] as $path) {
try { readReport($path, 9000); }
catch (RuntimeException $error) { echo $error->getMessage(), "\n"; }
}
Ожидаемый результат
id;qty
7;2
Повреждённый Bzip2
Превышен лимит
Оба отказа происходят до возврата текста. Это не универсальная проверка контейнера: добавленные после первого завершённого потока байты/второй поток этим API могут игнорироваться. Нужен согласованный формат и при необходимости доверенный размер/хеш исходного документа.
Договор этой функции: путь уже выбран приложением в контролируемом каталоге; это не произвольный URL пользователя. Она не реализует загрузку HTTP, таймаут, разбор CSV или транзакцию. Следующие этапы: проверка загруженного файла, разбор CSV, подтверждение импорта транзакцией. Сжатие не делает присланный SQL безопасным: импорт SQL выполняет команды, а не просто читает таблицу.
Где расходуется время и память
Сжатие и распаковка выполняются синхронно в текущем PHP-процессе. Строковые функции держат вход и выход в памяти; потоковое чтение ограничивает размер передаваемых приложению порций, но у библиотеки остаются внутренние блоки. Большая степень сжатия входа не гарантирует малый результат. Для больших выгрузок нужен фоновый обработчик, лимиты процесса и политика отмены; bzread сам не является планировщиком или таймаутом.
block_size у bzcompress — множитель размера одного блока: значение 1…9 означает 100 000…900 000 байт, а не количество блоков файла. Он влияет на память компрессора и распаковщика. work_factor определяет переключение алгоритма на повторяющихся данных, а не качество результата. У use_less_memory экономится внутренняя рабочая память распаковщика ценой времени; строка полного результата всё равно размещается в PHP. Фактическую стоимость измеряют на своих CSV, а не по имени режима.
| Когда достаточно | Что выбрать |
|---|---|
| Маленький текст и известный предел | bzcompress/bzdecompress с проверкой типов и договора целостности. |
| Большой файл | bzopen/bzread/bzwrite, обработка порциями; отказаться от накопления всего результата. |
| Нужен немедленно читаемый журнал | Обычная потоковая запись или отдельные завершённые части, а не bzflush. |
| Контейнер из нескольких файлов | Отдельная работа с форматом контейнера и безопасными путями распаковки. |
Упражнение: файл для скачивания и проверяемое восстановление
Сделайте файл с двумя строками статусов заказа, закройте поток и убедитесь, что чтение вернуло обе строки. Не вызывайте bzcompress перед bzwrite. Предложенный вариант проверяет объём записи и использует finally для освобождения ресурса.
- order=7;paid=1 и order=9;paid=0
- Передать обе обычные строки через bzwrite
- Закрыть поток
- Прочитать и сравнить восстановленный текст
<?php
$report = "order=7;paid=1\norder=9;paid=0\n";
$handle = bzopen('orders.bz2', 'w');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
if (bzwrite($handle, $report) !== strlen($report)) {
throw new RuntimeException('Неполная запись');
}
} finally { bzclose($handle); }
$restored = bzdecompress(file_get_contents('orders.bz2'));
var_dump($restored === $report);
echo $restored;
Ожидаемый результат
bool(true)
order=7;paid=1
order=9;paid=0
Такой небольшой круг записи/чтения полезен при настройке интеграции. Для выдачи браузеру отдельно задают заголовки и проверяют право доступа; бинарные байты не вставляют в HTML.
Усложнение: замените один байт входа или обрежьте файл и пропустите его через функцию из предыдущего раздела. Сформулируйте отдельно, что означает «файл прочитан», «Bzip2 не сообщил ошибку» и «поставщик прислал полный правильный документ». Это разные проверки.
Все функции Bzip2 по действиям
| Действие | Функции |
|---|---|
| Строки в памяти | bzcompress(), bzdecompress() |
| Открыть и завершить | bzopen(), bzclose() |
| Порции байтов | bzread(), bzwrite() |
| Диагностика ресурса | bzerrno(), bzerrstr(), bzerror() |
| Историческое ограничение | bzflush() |
Каждая карточка ниже содержит полный договор параметров, результат и отказы, минимальный опыт, прикладной случай и связи. В официальном дереве Bzip2 нет отдельной страницы констант/INI-настроек; их отсутствие объяснено в разделе установки.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
bzcompressУменьшить текст отчёта перед хранением или передачей. Результат — двоичная строка Bzip2, а не имя файла.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzcompress(string $data, int $block_size = 4, int $work_factor = 0): string|intУменьшить текст отчёта перед хранением или передачей. Результат — двоичная строка Bzip2, а не имя файла.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzcompress(string $data, int $block_size = 4, int $work_factor = 0): string|int
| Параметр | Договор |
|---|---|
| $data | Исходные байты: текст, CSV, JSON или другое содержимое. Функция не перекодирует текст. |
| $block_size | 1…9: блоки по 100 000 байт. Больше блок — больше рабочей памяти; 9 ориентирован на лучшее сжатие, но не обещает выигрыш для любого короткого входа. |
| $work_factor | 0…250: порог усилий перед запасным алгоритмом для повторяющихся данных. 0 означает библиотечное значение 30; это не уровень качества. При одном block_size результат не зависит от work_factor. |
Результат и ошибки. Сжатая строка либо целое число ошибки. Проверяйте is_string. С PHP 8.5 неверные диапазоны block_size/work_factor вызывают ValueError; в прежних версиях возможен числовой отказ библиотеки. Неподходящий тип аргумента даёт TypeError.
- Текст SKU-7;2
- bzcompress сжимает байты в строку
- bzdecompress восстанавливает исходный текст
<?php
$packed = bzcompress('SKU-7;2');
var_dump(is_string($packed));
echo bzdecompress($packed), "\n";
Ожидаемый результат
bool(true)
SKU-7;2
Сжатые байты не выводим как HTML: там могут быть нулевые и непечатные символы. Короткая строка может после сжатия стать больше.
Теперь вынесем упаковку повторяющегося отчёта в функцию: return возвращает строку вызывающему коду, а is_string отделяет её от кода ошибки. str_repeat повторяет учебную строку, strlen считает байты.
<?php
function packReport($text) {
$packed = bzcompress($text, 9, 0);
if (!is_string($packed)) {
throw new RuntimeException('Ошибка сжатия: ' . $packed);
}
return $packed;
}
$csv = str_repeat("SKU-7;2\n", 100);
$packed = packReport($csv);
var_dump(strlen($packed) < strlen($csv));
var_dump(bzdecompress($packed) === $csv);
var_dump(bzcompress($csv, 4, 0) === bzcompress($csv, 4, 30));
Ожидаемый результат
bool(true)
bool(true)
bool(true)
Здесь проверены уменьшение именно этого набора и обратимость. Равенство вариантов work_factor не является замером скорости.
<?php
foreach ([[0, 0], [4, 251]] as [$block, $work]) {
try { bzcompress('report', $block, $work); }
catch (ValueError $error) { echo "Неверная настройка\n"; }
}
Ожидаемый результат
Неверная настройка
Неверная настройка
Этот случай требует PHP 8.5+: catch перехватывает ValueError. В прикладной форме диапазоны проверяют до вызова, а не делают ошибку обычной веткой управления.
Границы применения. Вход и выход одновременно занимают память; это не потоковая обработка большого файла. При больших выгрузках используйте bzopen/bzwrite. Не путайте Bzip2 с gzip, zlib и ZIP: принимающая сторона должна ожидать тот же формат.
Связанные действия: bzdecompress(), bzopen(), bzwrite().
bzdecompressВернуть исходные байты из небольшой сжатой строки, например из сохранённого отчёта.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzdecompress(string $data, bool $use_less_memory = false): string|int|falseВернуть исходные байты из небольшой сжатой строки, например из сохранённого отчёта.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzdecompress(string $data, bool $use_less_memory = false): string|int|false
| Параметр | Договор |
|---|---|
| $data | Сжатые байты Bzip2, а не путь к .bz2. Для пути используйте bzopen/bzread. |
| $use_less_memory | true включает более экономный внутренний алгоритм. Тип bool с PHP 8.0; до этого int. Для больших блоков документация оценивает рабочую память примерно в 2300 КБ при примерно двукратном замедлении; это не предел всей памяти PHP. |
Результат и ошибки. Строка, false или целый код ошибки. Пустая строка и "0" допустимы, поэтому if (!$result) неверно. Успешный тип сам по себе не доказывает полноту произвольного внешнего входа: поведение обрезанного потока разобрано ниже.
- Bzip2-строка содержит отчёт "0"
- bzdecompress возвращает строку
- is_string подтверждает тип; echo показывает 0
<?php
$text = bzdecompress(bzcompress('0'));
var_dump(is_string($text));
echo $text, "\n";
Ожидаемый результат
bool(true)
0
Число ошибки и текст "0" отличаются типом. Проверка is_string сохраняет это различие.
<?php
$bad = bzdecompress('not a bzip2 stream');
echo is_string($bad) ? "Текст\n" : "Отказ\n";
$packed = bzcompress("id;total\n7;450\n");
var_dump(bzdecompress($packed, true) === bzdecompress($packed, false));
Ожидаемый результат
Отказ
bool(true)
Экономный режим меняет алгоритм, а не содержимое. Здесь нет утверждения о времени на другом компьютере.
Две независимые границы: PHP 8.5.11/libbzip2 1.0.8 возвращает только первый поток при склейке двух Bzip2-потоков; на данном обрезанном входе возвращает часть текста. Не переносите на этот вызов поведение утилиты bunzip2 для нескольких потоков.
<?php
$joined = bzcompress('ONE') . bzcompress('TWO');
echo bzdecompress($joined), "\n";
$original = str_repeat('A', 10000);
$truncated = substr(bzcompress($original), 0, -10);
$result = bzdecompress($truncated);
var_dump(is_string($result));
var_dump(is_string($result) && strlen($result) < strlen($original));
Ожидаемый результат
ONE
bool(true)
bool(true)
Зафиксированное поведение проверенной версии, не обещание одинакового размера частичного результата для любых данных. Договор источника должен включать полноту/размер/контрольную сумму; для файлов ниже показана проверка bzerror при чтении.
Границы применения. Весь распакованный результат создаётся в памяти. У малого входа может быть большой выход. Функция не даёт лимита результата или универсальной проверки, что потреблены все входные байты; для внешнего импорта нужны ограничения и отдельный договор целостности.
Связанные действия: bzcompress(), bzopen(), bzread(), bzerror().
bzopenОткрыть файл .bz2 так, чтобы последующие чтения и записи работали с обычным текстом.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzopen(string|resource $file, string $mode): resource|falseОткрыть файл .bz2 так, чтобы последующие чтения и записи работали с обычным текстом.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzopen возвращает ресурс — временный указатель на открытый поток, либо false при отказе. Это не содержимое файла. if (...) { ... } выбирает ветку; throw new RuntimeException(...) останавливает обычный путь с описанием ошибки. В try { ... } finally { bzclose($handle); } блок finally освобождает поток даже при исключении, но не подавляет ошибку. Потоки и позиция чтения; Обработка ошибки.
bzopen(string|resource $file, string $mode): resource|false
| Параметр | Договор |
|---|---|
| $file | Путь к файлу или уже открытый поток, допускающий файловый дескриптор и совместимый режим. Не всякий поток в памяти можно так обернуть. |
| $mode | Только "r" для чтения или "w" для записи. "w" создаёт файл либо обнуляет существующий. Прямого режима добавления "a", "r+" или "rb" нет. |
Результат и ошибки. Ресурс либо false, например при невозможности открыть путь; операция открытия может выдать warning. Ошибочный режим в PHP 8.5.11 вызывает ValueError. Неподходящий ресурс/режим исходного потока тоже проверяется. Не рассчитывайте, что все ошибки представляются только false.
- report.bz2 открывается для записи
- bzwrite получает обычный REPORT
- bzclose завершает файл; новый режим r читает REPORT
<?php
$handle = bzopen('report.bz2', 'w');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
bzwrite($handle, 'REPORT');
bzclose($handle);
$handle = bzopen('report.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try { echo bzread($handle), "\n"; }
finally { bzclose($handle); }
Ожидаемый результат
REPORT
В самостоятельном опыте путь находится в рабочей папке. На сайте заранее выбирают служебную директорию, а не принимают путь из формы.
<?php
file_put_contents('source.bz2', bzcompress('INVOICE'));
$raw = fopen('source.bz2', 'rb');
if ($raw === false) { throw new RuntimeException('Не открыт источник'); }
$compressed = bzopen($raw, 'r');
if ($compressed === false) { fclose($raw); throw new RuntimeException('Нет Bzip2-потока'); }
try { echo bzread($compressed), "\n"; }
finally { bzclose($compressed); }
var_dump(is_resource($raw));
Ожидаемый результат
INVOICE
bool(false)
Здесь rb относится к fopen, а r — к bzopen. В проверенной реализации закрытие обёртки закрывает и исходный поток: не вызывайте затем fclose ещё раз.
Границы применения. Переданный файловый поток должен стоять в начале нужного сжатого потока; предварительное чтение заголовка сдвигает позицию. Режим чтения файла не подтверждает корректность Bzip2: неверный формат часто обнаруживается только при bzread. Для потоковых обёрток см. схемы и контексты.
Связанные действия: bzread(), bzwrite(), bzclose(), bzerror().
bzreadПрочитать порцию распакованных байтов из файла, не собирая весь результат сразу.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzread(resource $bz, int $length = 1024): string|falseПрочитать порцию распакованных байтов из файла, не собирая весь результат сразу.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzopen возвращает ресурс — временный указатель на открытый поток, либо false при отказе. Это не содержимое файла. if (...) { ... } выбирает ветку; throw new RuntimeException(...) останавливает обычный путь с описанием ошибки. В try { ... } finally { bzclose($handle); } блок finally освобождает поток даже при исключении, но не подавляет ошибку. Потоки и позиция чтения; Обработка ошибки.
bzread(resource $bz, int $length = 1024): string|false
| Параметр | Договор |
|---|---|
| $bz | Открытый ресурс bzopen в режиме r; позиция продвигается после чтения. |
| $length | Максимум запрошенных распакованных байтов, по умолчанию 1024; за один вызов не больше 8192. Результат может быть короче. 0 даёт пустую строку; отрицательное значение в PHP 8 вызывает ValueError. |
Результат и ошибки. Строка либо false при ошибке. Конец корректного потока даёт пустую строку; сверяйте bzerror, поскольку EOF бывает также на повреждённом входе. Длина измеряется в байтах, граница порции может пройти посередине UTF-8 символа или CSV-строки.
- Исходный текст ABCDEF
- bzread(..., 2) → AB и сдвиг позиции
- Следующий bzread(..., 2) → CD
<?php
file_put_contents('letters.bz2', bzcompress('ABCDEF'));
$handle = bzopen('letters.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
echo bzread($handle, 2), "\n";
echo bzread($handle, 2), "\n";
} finally { bzclose($handle); }
Ожидаемый результат
AB
CD
Один и тот же ресурс помнит позицию. Два вызова не возвращают начало файла заново.
while (true) повторяет действия, break останавливает цикл; += увеличивает счётчик. Проверяем ошибку до использования порции. Циклы и выход.
<?php
file_put_contents('batch.bz2', bzcompress(str_repeat('A', 10000)));
$handle = bzopen('batch.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
$total = 0;
try {
while (true) {
$chunk = bzread($handle, 4096);
$error = bzerror($handle);
if ($chunk === false || $error['errno'] !== 0) {
throw new RuntimeException('Ошибка Bzip2: ' . $error['errstr']);
}
if ($chunk === '') { break; }
if (strlen($chunk) > 12000 - $total) {
throw new RuntimeException('Лимит распаковки');
}
$total += strlen($chunk);
}
} finally { bzclose($handle); }
echo $total, "\n";
Ожидаемый результат
10000
Счётчик не накапливает весь текст. Предел 12 000 относится к выходным байтам этого опыта; библиотека всё равно имеет внутренние буферы. Здесь ещё нет CSV-парсинга, записи в базу или таймаута.
Границы применения. Короткая порция сама по себе не доказывает конец. Для данных вне доверенного источника ограничивают также размер входа, длительность задачи и область записи; завершённые бизнес-изменения делают после проверки всего документа. feof без проверки ошибки недостаточен.
bzwriteПередать обычные байты в открытый Bzip2-файл; сжатие выполняется внутри потока.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzwrite(resource $bz, string $data, ?int $length = null): int|falseПередать обычные байты в открытый Bzip2-файл; сжатие выполняется внутри потока.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzopen возвращает ресурс — временный указатель на открытый поток, либо false при отказе. Это не содержимое файла. if (...) { ... } выбирает ветку; throw new RuntimeException(...) останавливает обычный путь с описанием ошибки. В try { ... } finally { bzclose($handle); } блок finally освобождает поток даже при исключении, но не подавляет ошибку. Потоки и позиция чтения; Обработка ошибки.
bzwrite(resource $bz, string $data, ?int $length = null): int|false
| Параметр | Договор |
|---|---|
| $bz | Пишущий Bzip2-ресурс от bzopen(..., "w"). |
| $data | Несжатая строка. Предварительный bzcompress создаст двойное сжатие. |
| $length | Максимум байтов исходной строки: запись останавливается на length либо конце data — что наступит раньше. null означает всю строку; параметр nullable с PHP 8.0. Длина не является числом Unicode-символов или размером файла после сжатия. В реализации PHP 8.5.11 нулевая/отрицательная длина ничего не пишет и даёт 0. |
Результат и ошибки. Количество принятых исходных байтов, либо false. Сравнивайте с длиной переданного фрагмента; 0 — не false и не означает успешную запись непустого фрагмента. Это алиас потоковой записи fwrite в реализации PHP.
- ABCDEF — обычный текст
- bzwrite с length 3 принимает ABC
- После закрытия чтение даёт ABC
<?php
$handle = bzopen('prefix.bz2', 'w');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try { echo bzwrite($handle, 'ABCDEF', 3), "\n"; }
finally { bzclose($handle); }
echo bzdecompress(file_get_contents('prefix.bz2')), "\n";
Ожидаемый результат
3
ABC
В файл попадёт сжатое представление ABC, а не строка ABCDEF и не три сжатых байта.
Следующий пример использует массив строк и foreach: каждая строка целиком передаётся одной операцией. При неполной записи выбран отказ, а не скрытое принятие повреждённого отчёта.
<?php
$lines = ["id;qty\n", "7;2\n", "9;1\n"];
$handle = bzopen('stock.bz2', 'w');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
foreach ($lines as $line) {
if (bzwrite($handle, $line) !== strlen($line)) {
throw new RuntimeException('Неполная запись');
}
}
} finally { bzclose($handle); }
echo bzdecompress(file_get_contents('stock.bz2'));
Ожидаемый результат
id;qty
7;2
9;1
Порции входят как обычный текст. Для реальной публикации выгрузку сначала пишут в новый служебный файл и проверяют; этот пример не реализует протокол атомарной замены.
Границы применения. Закрытие завершает сжатый поток. Не открывайте заново тот же путь с w для каждой строки: старое содержимое будет обнулено. Не считайте bzflush способом сделать промежуточный файл завершённым.
Связанные действия: bzopen(), bzclose(), bzflush(), bzcompress().
bzcloseЗавершить работу с ресурсом; для пишущего потока закончить формирование .bz2.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzclose(resource $bz): boolЗавершить работу с ресурсом; для пишущего потока закончить формирование .bz2.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzopen возвращает ресурс — временный указатель на открытый поток, либо false при отказе. Это не содержимое файла. if (...) { ... } выбирает ветку; throw new RuntimeException(...) останавливает обычный путь с описанием ошибки. В try { ... } finally { bzclose($handle); } блок finally освобождает поток даже при исключении, но не подавляет ошибку. Потоки и позиция чтения; Обработка ошибки.
bzclose(resource $bz): bool
| Параметр | Договор |
|---|---|
| $bz | Открытый ресурс Bzip2. После закрытия он больше не пригоден для чтения, записи или диагностики. |
Результат и ошибки. true при успешном закрытии, false при отказе. Закрытый или неподходящий ресурс может вызвать TypeError. true не является доказательством физической сохранности диска или полноты исходного бизнес-документа.
- Пишущий ресурс принимает READY
- bzclose завершает поток
- Файл можно открыть отдельным читателем
<?php
$handle = bzopen('ready.bz2', 'w');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
bzwrite($handle, 'READY');
var_dump(bzclose($handle));
var_dump(is_resource($handle));
echo bzdecompress(file_get_contents('ready.bz2')), "\n";
Ожидаемый результат
bool(true)
bool(false)
READY
Файл остаётся на диске; закрывается ресурс, а не удаляется содержимое.
<?php
file_put_contents('report.bz2', bzcompress('wrong-header'));
$handle = bzopen('report.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
try {
if (bzread($handle) !== 'id;qty') {
throw new RuntimeException('Неверный заголовок');
}
} finally { bzclose($handle); }
} catch (RuntimeException $error) {
echo $error->getMessage(), "\n";
}
var_dump(is_resource($handle));
Ожидаемый результат
Неверный заголовок
bool(false)
Внутренний finally освобождает ресурс, внешний catch сообщает причину отказа. Прикладная ошибка не исчезает из-за закрытия файла.
Границы применения. Состояние bzerror считывайте до закрытия. При передаче в bzopen существующего файлового ресурса закрытие обёртки закрывает также исходный ресурс в проверенной реализации. Закрывать дважды не нужно.
bzflushРаспознать ограничение старого совместимого API: этот вызов не делает полезной принудительной выгрузки Bzip2-буфера.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzflush(resource $bz): boolРаспознать ограничение старого совместимого API: этот вызов не делает полезной принудительной выгрузки Bzip2-буфера.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzopen возвращает ресурс — временный указатель на открытый поток, либо false при отказе. Это не содержимое файла. if (...) { ... } выбирает ветку; throw new RuntimeException(...) останавливает обычный путь с описанием ошибки. В try { ... } finally { bzclose($handle); } блок finally освобождает поток даже при исключении, но не подавляет ошибку. Потоки и позиция чтения; Обработка ошибки.
bzflush(resource $bz): bool
| Параметр | Договор |
|---|---|
| $bz | Открытый пишущий ресурс Bzip2. |
Результат и ошибки. Булев результат вызова. Официальная документация прямо отмечает: библиотечный BZ2_bzflush ничего не делает. true нельзя трактовать как готовность файла к чтению, завершение потока или гарантию сохранения на диск.
- ABC записывается в Bzip2-поток
- bzflush может вернуть true, но не завершает поток
- Только затем bzclose; читаем готовый файл
<?php
$handle = bzopen('flush.bz2', 'w');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
bzwrite($handle, 'ABC');
var_dump(bzflush($handle));
bzclose($handle);
echo bzdecompress(file_get_contents('flush.bz2')), "\n";
Ожидаемый результат
bool(true)
ABC
Чтение сделано после bzclose. Этот опыт намеренно не приписывает bzflush появление готового результата.
<?php
$handle = bzopen('parts.bz2', 'w');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
bzwrite($handle, "part-1\n");
bzflush($handle);
bzwrite($handle, "part-2\n");
} finally { bzclose($handle); }
echo bzdecompress(file_get_contents('parts.bz2'));
Ожидаемый результат
part-1
part-2
Это объяснение встреченного в старом проекте вызова, а не рекомендация вставлять его между порциями. Для независимо готовых частей создают отдельные завершённые файлы.
Границы применения. Не переносите обещания fflush обычного потока на эту обёртку. Если читатель должен видеть обновления в реальном времени, выберите иной протокол/несжатый журнал либо закрывайте отдельные сжатые части.
bzerrnoПолучить числовой код последней ошибки потока и выбрать ветку обработки.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzerrno(resource $bz): intПолучить числовой код последней ошибки потока и выбрать ветку обработки.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzopen возвращает ресурс — временный указатель на открытый поток, либо false при отказе. Это не содержимое файла. if (...) { ... } выбирает ветку; throw new RuntimeException(...) останавливает обычный путь с описанием ошибки. В try { ... } finally { bzclose($handle); } блок finally освобождает поток даже при исключении, но не подавляет ошибку. Потоки и позиция чтения; Обработка ошибки.
bzerrno(resource $bz): int
| Параметр | Договор |
|---|---|
| $bz | Ещё открытый ресурс именно Bzip2 после проверяемой операции. Закрытый или обычный fopen-ресурс не подходит для этих диагностических функций. |
Результат и ошибки. Целое число: 0 означает отсутствие ошибки, отрицательное — отказ. Это не число прочитанных байтов и не HTTP-код. Если bzopen вернул false, диагностического ресурса ещё нет: эту функцию не вызывают.
- Файл содержит корректный сжатый OK
- bzread читает его
- Диагностика сообщает отсутствие ошибки
<?php
file_put_contents('ok.bz2', bzcompress('OK'));
$handle = bzopen('ok.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
bzread($handle);
echo bzerrno($handle), "\n";
} finally { bzclose($handle); }
Ожидаемый результат
0
Проверка относится к операции чтения на этом ресурсе. Для целого кода из bzdecompress нет отдельного ресурса, который можно передать сюда.
Теперь имя заканчивается .bz2, но содержимое обычное. bzopen смог открыть файл; ошибка формата появилась при bzread. Результат чтения не используют до проверки состояния.
<?php
file_put_contents('fake.bz2', 'ordinary report');
$handle = bzopen('fake.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
bzread($handle);
echo bzerrno($handle) === -5 ? "Неверный формат\n" : "Другая ошибка\n";
} finally { bzclose($handle); }
Ожидаемый результат
Неверный формат
Показанное обозначение пришло из libbzip2 1.0.8. В пользовательском интерфейсе лучше вывести «Не удалось прочитать отчёт», а техническое состояние записать во внутреннюю диагностику.
Границы применения. Считайте состояние сразу после операции и до bzclose. В PHP эти имена библиотечных ошибок не экспортированы как BZ_* константы. Таблица кодов есть в разделе диагностики. Код 0 после конца чтения не доказывает отсутствие лишних байтов/второго сжатого потока после первого.
Связанные действия: bzerrstr(), bzerror(), bzread().
bzerrstrПолучить техническое описание ошибки для внутренней диагностики.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzerrstr(resource $bz): stringПолучить техническое описание ошибки для внутренней диагностики.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzopen возвращает ресурс — временный указатель на открытый поток, либо false при отказе. Это не содержимое файла. if (...) { ... } выбирает ветку; throw new RuntimeException(...) останавливает обычный путь с описанием ошибки. В try { ... } finally { bzclose($handle); } блок finally освобождает поток даже при исключении, но не подавляет ошибку. Потоки и позиция чтения; Обработка ошибки.
bzerrstr(resource $bz): string
| Параметр | Договор |
|---|---|
| $bz | Ещё открытый ресурс именно Bzip2 после проверяемой операции. Закрытый или обычный fopen-ресурс не подходит для этих диагностических функций. |
Результат и ошибки. Строка технического состояния, например OK или DATA_ERROR_MAGIC. Она не предназначена для прямого сообщения пользователю и не заменяет проверку кода. Если bzopen вернул false, диагностического ресурса ещё нет: эту функцию не вызывают.
- Файл содержит корректный сжатый OK
- bzread читает его
- Диагностика сообщает отсутствие ошибки
<?php
file_put_contents('ok.bz2', bzcompress('OK'));
$handle = bzopen('ok.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
bzread($handle);
echo bzerrstr($handle), "\n";
} finally { bzclose($handle); }
Ожидаемый результат
OK
Проверка относится к операции чтения на этом ресурсе. Для целого кода из bzdecompress нет отдельного ресурса, который можно передать сюда.
Теперь имя заканчивается .bz2, но содержимое обычное. bzopen смог открыть файл; ошибка формата появилась при bzread. Результат чтения не используют до проверки состояния.
<?php
file_put_contents('fake.bz2', 'ordinary report');
$handle = bzopen('fake.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
bzread($handle);
echo bzerrstr($handle), "\n";
} finally { bzclose($handle); }
Ожидаемый результат
DATA_ERROR_MAGIC
Показанное обозначение пришло из libbzip2 1.0.8. В пользовательском интерфейсе лучше вывести «Не удалось прочитать отчёт», а техническое состояние записать во внутреннюю диагностику.
Границы применения. Считайте состояние сразу после операции и до bzclose. В PHP эти имена библиотечных ошибок не экспортированы как BZ_* константы. Таблица кодов есть в разделе диагностики. Код 0 после конца чтения не доказывает отсутствие лишних байтов/второго сжатого потока после первого.
bzerrorПолучить код и описание одной ошибочной операции вместе.
PHP 4.0.4+; примеры PHP 8.2+ · bz2 / libbzip2
bzerror(resource $bz): arrayПолучить код и описание одной ошибочной операции вместе.
Вызов имя(...) передаёт значения функции; запятые разделяют аргументы. $name = ...; сохраняет результат, echo выводит его, а var_dump показывает также тип. "\n" — перевод строки. === false проверяет именно отказ, не пустой текст и не строку "0". Переменная; Вызов функции.
bzopen возвращает ресурс — временный указатель на открытый поток, либо false при отказе. Это не содержимое файла. if (...) { ... } выбирает ветку; throw new RuntimeException(...) останавливает обычный путь с описанием ошибки. В try { ... } finally { bzclose($handle); } блок finally освобождает поток даже при исключении, но не подавляет ошибку. Потоки и позиция чтения; Обработка ошибки.
bzerror(resource $bz): array
| Параметр | Договор |
|---|---|
| $bz | Ещё открытый ресурс именно Bzip2 после проверяемой операции. Закрытый или обычный fopen-ресурс не подходит для этих диагностических функций. |
Результат и ошибки. Ассоциативный массив с errno (int) и errstr (string). Ключи читают через квадратные скобки: $error['errno']. Массив сам по себе не булев признак ошибки. Если bzopen вернул false, диагностического ресурса ещё нет: эту функцию не вызывают.
- Файл содержит корректный сжатый OK
- bzread читает его
- Диагностика сообщает отсутствие ошибки
<?php
file_put_contents('ok.bz2', bzcompress('OK'));
$handle = bzopen('ok.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
bzread($handle);
$error = bzerror($handle);
echo $error['errno'], ":", $error['errstr'], "\n";
} finally { bzclose($handle); }
Ожидаемый результат
0:OK
Проверка относится к операции чтения на этом ресурсе. Для целого кода из bzdecompress нет отдельного ресурса, который можно передать сюда.
Теперь имя заканчивается .bz2, но содержимое обычное. bzopen смог открыть файл; ошибка формата появилась при bzread. Результат чтения не используют до проверки состояния.
<?php
file_put_contents('fake.bz2', 'ordinary report');
$handle = bzopen('fake.bz2', 'r');
if ($handle === false) { throw new RuntimeException('Не открыт файл'); }
try {
bzread($handle);
$error = bzerror($handle);
echo $error['errno'], ":", $error['errstr'], "\n";
} finally { bzclose($handle); }
Ожидаемый результат
-5:DATA_ERROR_MAGIC
Показанное обозначение пришло из libbzip2 1.0.8. В пользовательском интерфейсе лучше вывести «Не удалось прочитать отчёт», а техническое состояние записать во внутреннюю диагностику.
Границы применения. Считайте состояние сразу после операции и до bzclose. В PHP эти имена библиотечных ошибок не экспортированы как BZ_* константы. Таблица кодов есть в разделе диагностики. Код 0 после конца чтения не доказывает отсутствие лишних байтов/второго сжатого потока после первого.
Связанные действия: bzerrno(), bzerrstr(), bzread().
Источники и обсуждения
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


