Как упоминалось ранее, бинарные данные обычно предполагают выполнение дополнительной операции над всеми значениями, содержащимися в считанных данных, для преобразования их к виду, пригодному для использования в РНР.
Этот процесс (называемый распаковкой) выполняется с помощью функции unpack!), которая имеет следующий синтаксис:
unpack($format, $data)
где $data представляет собой данные, которые необходимо распаковать, а строка $format — это строка описания, содержащая коды формата и имена переменных, в которых сохраняются распакованные значения. При составлении строки описания $format используются те же самые коды, что и для упаковки бинарных данных, а сама строка имеет следующий вид:
<коды формата><имя переменной>/<коды формата><имя переменной>
При успешном завершении unpack () возвращает ассоциативный массив, содержащий для каждого ключа <имя переменной> соответствующее значение, распакованное из строки $data.
Распаковка бинарных данных с помощью unpack ()
<?php /* Предположим, что в бинарной строке $data упакованы два целочисленных значения */ $bdata = unpack("nintl/nint2" , $data); echo "Первое целое число в упакованных данных: {$bdata['intl']}<BR>"; echo "Второе целое число в упакованных данных: ($bdata['int2']}<BR>"; ?>
Объединив эти функции вместе, мы в состоянии написать программу, которая извлекает версию заданного Zip-файла. Но для этого нам нужно еще знать, где искать эту информацию внутри архива. Если вы обратитесь к любимой поисковой системе, то сможете быстро получить документацию по данному широко используемому формату, но мы сэкономили ваше время и проделали эту работу за вас.
Нас будут интересовать пятый и шестой байты файла (именно в этих байтах содержится информация о версии Zip-файла). Теперь у нас есть все необходимое для создания функции, которую мы назовем getZipVer(), извлечения версии из произвольного Zip-файла.
Получение версии Zip-файла
<?php function getZipVer($zipfile) { $quote_val = get_magic_quotes_runtime(); set_magic_quotes_runtime(false) ; $fr = @fopen($zipfile, 'rb'); if(!$fr) return false; if (fseek($fr,4) == ~D return false; $ver = fread($fr, 2); fclose($fr); $values unpack("vversion", $ver); $verdata = array('major' => $values['version'] / 10, 'minor' => $values['version'] % 10); set_magic_quotes_runtime($quote_val); return $verdata; } $version = getZipVer('test.zip'); if(!$version) { echo "Ошибка при чтении информации об версии!"; } else { echo "Версия: {$version['major']}(основной номер)" . ", {$version['minor']}(дополнительный номер)"; } ?>
Первым делом функция getZipVerf () отключает «магические кавычки» (текущее значение этого конфигурационного параметра сохраняется в переменной). Затем файл открывается для чтения в бинарном режиме и при помощи функции fseek() указатель файла передвигается в позицию со смещением 4. После этого из файла считываются два байта (информация о версии) и файл закрывается.
После того как требуемые данные прочитаны из файла, их необходимо распаковать для того, чтобы они имели смысл для РНР, и с ними можно было работать. Согласно спецификации Zip-файла, в этих двух байтах содержится 16-битное целое без знака. Это число, поделенное на 10, представляет старший номер версии Zip-файла, в то время как это же число по модулю 10 представляет младший номер версии. Используя код формата v для функции unpack О, это число распаковывается из двоичных данных и помещается в ключ ‘version’ возвращаемого массива, который в свою очередь сохраняется в массиве $values.
Затем этот массив используется при создании массива $verdata, который в результате содержит два значения, соответствующие старшему и младшему номерам версии Zip-файла. В конце работы функция восстанавливает сохраненное состояние «магических кавычек», после чего завершает свою работу и возвращает массив с информацией о версии. Эти числа затем отображаются клиенту и на этом выполнение программы завершается.