Php byte to long

Работа с бинарными данными в php

PHP как язык плохо подходит для работы бинарными данными напрямую. Но иногда приложения должны взаимодействовать по таким протоколам, где размер пакетов очень важен или родным форматом данных для какого-то приложения, который никем в красивый json или xml не переводится.

Целые типы данных

Напоминаю какие типы данных есть в Си, на котором основан php

Тип Размер памяти Значений всего
char 1 байт = 8 бит 256
int 2 байт = 16 бит 2^16=65536
short 2 байта
long 4 байта = 32 бита 4294967295

Char при этом используется универсально согласно ASCII табличке как в качестве явного кодирования текста, так и вспомогательными маркерами. Про float я умолчу, ибо мне не понадобилось.

Нотация

Если с бинарными данными не работать, то можно и забыть основы языка. С целыми числами на основании 10 всё понятно, но обычно значения длинных данных в них не пишут. Это объясняет табличку выше.

  • Бинарная, например 0b1011
  • Восьмеричная, например 0123
  • Шестнадцатиричная, например 0xF560B1A9

Кроме этого, если вы переписываетесь с коллегами которые пишут на си, то они могут обозначать приставками или окончаниями

  • Unsigned int 14u
  • Long double или long int. Например 1.2l или 1L — фиг поймёшь, это единица или long
  • Float (с плавающей запятой) 1.3f или 1.3F

Итого, у нас char a будет хранить значение от -128 до 127.. ну или 256 если это extended ASCII. Отлично. Теперь как это использовать в php?

Порядок битов

Честно, для меня было откровением что порядок в данных имеет значение. Я привык что 123 уже подразумевает где сотни, десятки и единицы, но для компьютера ведь всё равно. Конечно одно дело порядок написания для человека.. но тут другое — порядок записи байтов в зависимости от адреса. И больше всего удивительно что архитектуры на уровне работы с памятью разделились — x86 на стороне little endian, а за big endian SPARC и прочие. Поэтому если вы интегрируете разные архитектуры с бинарным форматом данных — договоритесь которая система будет работать.

Операции

1. Бинарное чтение файла — fopen(«binaryfile»,»b»);

2. Битовые маски — популярный метод хранить много булевых значений в одной переменной и включать/проверять с помощью AND/OR операций. Если вы когда либо выполняли chmod 755, то уже включали эти флажки на привилий.

3. Побитовые сдвиги — помогают работать с битовыми масками и с битами в вообще

$b = $a >> 2 ; — сдвиг битов на две позиции вправо, тут может пригодится константа PHP_INT_SIZE
$b = 8 >> 3 ; // 1

4. Cyclic redundancy check

Проверка данных с помощью контрольных сумм увы для меня осталась за пределами понимания. Важно знать что биты суммируются, и что полиномы бывают разные. Соответсвенно алгоритмы тоже бывают разные и как правило неограничивается функцией crc32(). Гляньте на мою коллекцию и онлайн валидатор .

Читайте также:  Угадай случайное число python

Вот пример самого короткого кода для CRC16 CCITT

function crc16_ССITT($data) < $crc = 0xFFFF; for($i = 0; $i < strlen($data); $i++) < $x = (($crc >> 8) ^ ord($data[$i])) & 0xFF; $x ^= $x >> 4; $crc = (($crc 8) ^ ($x 12) ^ ($x 5) ^ $x) & 0xFFFF; > return $crc; >

5. Упаковка

Если вы обычную переменную в php начнёте сохранять в файл, то она наверняка не будет оптимальной. А если таких однородных данных много — то тем более имеет смысл создать более компактную версию.

Например, если вы хотите число 250 записать в один байт как char-тип, вместо того что-бы писать «строкой» в три символа, как то будет делать php по умолчанию, пишем:

Первый аргумент это формат данных по длине. Если все данные char-типа, то можно написать c* как в регулярных выражениях, получить повторение типа. Можно написать c4, что будет аналогично cccc (четыре повторения данных char-типа)

  • a — строка, свободные места в поле заполняются символом с кодом 0
  • A — строка, свободные места заполняются пробелами
  • h — шестнадцатеричная строка, младшие разряды в начале (little endian)
  • H — шестнадцатеричная строка, старшие разряды в начале (big endian)
  • c — 1 байт (signed char)
  • C — 1 байт (unsigned char)
  • x — символ с нулевым кодом
  • X — возврат назад на 1 байт
  • @ — заполнение нулевым кодом до заданной абсолютной позиции
  • s — short (16 bit)
  • S — unsigned short
  • n — short (big endian)
  • v — unsigned short (little endian)
  • i — integer (размер и порядок байтов определяется архитектурой)
  • I — unsigned integer
  • l — знаковое длинное целое (32 бита, порядок знаков определяется архитектурой)
  • L — беззнаковое длинное целое
  • N — беззнаковое длинное целое (32 бита, старшие разряды в конце)
  • V — беззнаковое целое (32 бита, младшие разряды в конце)

Сам не проверял, но говорят что unsigned int получить не так то просто

6. Распаковка

Для раскодирования используется unpack() с аналогичным форматом типов данных, только теперь можно добавлять названия ключей для результатов ассоциативного массива
unpack ( «cmessageid/Vtimestamp» , pack ( «H*» ,FFFF));

Заметьте что pack я тут использую вместо hex2bin, которая недоступна для версий php менее 5.4

7. Конвертирование

base_convert — конвертирование строковых представлений чисел из любого основания в другое (скажем 16 в 2)
bindec, decbin — конвертирование 2 двоичных и десятичных данных
octdec, decoct — конвертирование 10 десятичных и восьмеричных данных
hexdec, dechex — конвертирование 16 десятичных и шестнадцатиричных данных
ord, chr — конвертирование 256 десятичных и символьных (ascii) данных

base64_encode, base64_decode — конвертирование 256 данных, но в отличие от предыдущих форматов, данные одного значения не кодируются в 6 битах что-бы получить 64 значения, а по прежнему в 8 битах — остальные символы просто не используются.. Из-за этого формат менее эффективен в хранении, но для человека в виде текста более компактен чем нули, единицы или hex.

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

function str2bin($str, $mode=0, $visual_aid=true) < $out = false; for($a=0; $a < strlen($str); $a++) < $dec = ord(substr($str,$a,1)); $bin = ''; for($i=7; $i>=0; $i--) < if ( $dec >= pow(2, $i) ) < $bin .= "1"; $dec -= pow(2, $i); > else < $bin .= "0"; > > /* Default-mode */ if ( $mode == 0 ) $out .= $bin; /* Human-mode (easy to read) */ if ( $mode == 1 ) $out .= $bin . " "; /* Array-mode (easy to use) */ if ( $mode == 2 ) $out[$a] = $bin; if($visual_aid)< $out.=" "; > > return $out; > function str2dec($string, $visual_aid=true)< $hex=''; for ($i=0; $i < strlen($string); $i++) < $hex .= ord($string[$i]); if($visual_aid)< $hex.= "(".$string[$i].") "; > > return $hex; > function str2hex($string, $visual_aid=true)< $hex=''; for ($i=0; $i < strlen($string); $i++) < $hex .= dechex(ord($string[$i])); if($visual_aid)< $hex.= " "; > > return $hex; > function hex2str($hex)< $string=''; for ($i=0; $i < strlen($hex)-1; $i+=2) < $string .= chr(hexdec($hex[$i].$hex[$i+1])); > return $string; >

Читайте также

Простейший backdoor на php Backdoor — тайный ход, лазейка. Разумное человечество использовало всегда запасной случай что-бы не попасть впросак. К примеру те же замки,…

Читайте также:  Captcha php captcha class php

Сортировка матрицы на PHP Сортировку можно производить на стороне сервера в БД (самое логичное решение), но зачастую система не продумана заранее настолько и получается…

Cлучайные числа с плавающей точкой в PHP Стандартные библиотеки PHP умеют генерировать только целые случайные числа. Однако, возникают задачи где нужно не целое рандомное число с максимально…

Источник

pack

Pack given arguments into a binary string according to format .

The idea for this function was taken from Perl and all formatting codes work the same as in Perl. However, there are some formatting codes that are missing such as Perl’s «u» format code.

Note that the distinction between signed and unsigned values only affects the function unpack() , where as function pack() gives the same result for signed and unsigned format codes.

Parameters

The format string consists of format codes followed by an optional repeater argument. The repeater argument can be either an integer value or * for repeating to the end of the input data. For a, A, h, H the repeat count specifies how many characters of one data argument are taken, for @ it is the absolute position where to put the next data, for everything else the repeat count specifies how many data arguments are consumed and packed into the resulting binary string.

Currently implemented formats are:

pack() format characters
Code Description
a NUL-padded string
A SPACE-padded string
h Hex string, low nibble first
H Hex string, high nibble first
c signed char
C unsigned char
s signed short (always 16 bit, machine byte order)
S unsigned short (always 16 bit, machine byte order)
n unsigned short (always 16 bit, big endian byte order)
v unsigned short (always 16 bit, little endian byte order)
i signed integer (machine dependent size and byte order)
I unsigned integer (machine dependent size and byte order)
l signed long (always 32 bit, machine byte order)
L unsigned long (always 32 bit, machine byte order)
N unsigned long (always 32 bit, big endian byte order)
V unsigned long (always 32 bit, little endian byte order)
q signed long long (always 64 bit, machine byte order)
Q unsigned long long (always 64 bit, machine byte order)
J unsigned long long (always 64 bit, big endian byte order)
P unsigned long long (always 64 bit, little endian byte order)
f float (machine dependent size and representation)
g float (machine dependent size, little endian byte order)
G float (machine dependent size, big endian byte order)
d double (machine dependent size and representation)
e double (machine dependent size, little endian byte order)
E double (machine dependent size, big endian byte order)
x NUL byte
X Back up one byte
Z NUL-padded string
@ NUL-fill to absolute position
Читайте также:  span

Return Values

Returns a binary string containing data.

Changelog

Version Description
8.0.0 This function no longer returns false on failure.
7.2.0 float and double types supports both Big Endian and Little Endian.
7.0.15,7.1.1 The «e», «E», «g» and «G» codes were added to enable byte order support for float and double.

Examples

Example #1 pack() example

The resulting binary string will be 6 bytes long and contain the byte sequence 0x12, 0x34, 0x78, 0x56, 0x41, 0x42.

Notes

Note that PHP internally stores int values as signed values of a machine-dependent size (C type long ). Integer literals and operations that yield numbers outside the bounds of the int type will be stored as float . When packing these floats as integers, they are first cast into the integer type. This may or may not result in the desired byte pattern.

The most relevant case is when packing unsigned numbers that would be representable with the int type if it were unsigned. In systems where the int type has a 32-bit size, the cast usually results in the same byte pattern as if the int were unsigned (although this relies on implementation-defined unsigned to signed conversions, as per the C standard). In systems where the int type has 64-bit size, the float most likely does not have a mantissa large enough to hold the value without loss of precision. If those systems also have a native 64-bit C int type (most UNIX-like systems don’t), the only way to use the I pack format in the upper range is to create int negative values with the same byte representation as the desired unsigned value.

See Also

Источник

Оцените статью