Кодирование байтовых данных на цифры

Существует ли общий метод кодирования и декодирования произвольных данных, поэтому конечный результат кодирования состоит только из чисел – как base64_encode, но без букв?

Фиктивный пример:

$encoded = numbers_encode("Mary had a little lamb"); echo $encoded; // outputs eg 12238433742239423742322 (fictitious result) $decoded = numbers_decode("12238433742239423742322"); echo $decoded; // outputs "Mary had a little lamb" 

Вы можете представить строку с одним байтовым символом в виде номера с номером 256, где «\ x00» представляет 0, '' (пробел, т. Е. «\ X20»), представляет 32 и так далее до «\ xFF», что представляет 255.

Представление только с цифрами 0-9 может быть выполнено просто путем изменения представления на основание 10.

Обратите внимание, что «base64 encoding» на самом деле не является базовым преобразованием . base64 разбивает ввод на группы по 3 байта (24 бита) и делает базовое преобразование в этих группах индивидуально. Это хорошо работает, потому что число с 24 битами может быть представлено четырьмя цифрами в базе 64 (2 ^ 24 = 64 ^ 4).

Это более или менее то, что делает el.pescado – он разбивает входные данные на 8-битные фрагменты и затем преобразует число в базу 10. Однако этот метод имеет один недостаток относительно кодирования базы 64 – он не выравнивается правильно с байтовая граница. Чтобы представить число с 8-битами (0-255 при отсутствии знака), нам нужно три цифры в базе 10. Однако самая левая цифра имеет меньше информации, чем остальные. Это может быть 0, 1 или 2 (для неподписанных номеров).

Цифра в базе 10 хранит бит журнала (10) / log (2). Независимо от того, какой размер блока вы выберете, вы никогда не сможете согласовать представления с 8-битными байтами (в смысле «выравнивания», описанного выше в параграфе). Следовательно, самым компактным представлением является базовое преобразование (которое вы можете видеть, как будто это «базовая кодировка» только с одним большим куском).

Вот пример с bcmath .

 bcscale(0); function base256ToBase10(string $string) { //argument is little-endian $result = "0"; for ($i = strlen($string)-1; $i >= 0; $i--) { $result = bcadd($result, bcmul(ord($string[$i]), bcpow(256, $i))); } return $result; } function base10ToBase256(string $number) { $result = ""; $n = $number; do { $remainder = bcmod($n, 256); $n = bcdiv($n, 256); $result .= chr($remainder); } while ($n > 0); return $result; } 

Для

 $string = "Mary had a little lamb"; $base10 = base256ToBase10($string); echo $base10,"\n"; $base256 = base10ToBase256($base10); echo $base256; 

мы получаем

 36826012939234118013885831603834892771924668323094861
 У Мэри был маленький ягненок

Поскольку каждая цифра кодирует только log(10)/log(2)=~3.32193 бит, ожидается, что число будет иметь тенденцию быть на 140% длиннее (не на 200% больше, как и при ответе el.pescado).

Ну, это будет кодировка «base 8», а не Base 64. Это лучше знать как Octal.

Все Base64 выполняет преобразование битовых потоков в 6 бит блоков (0-63) и назначает символ из 64-символьного набора символов. Octal использует 3 бита, 0-7. Поэтому он МОЖЕТ использовать ABCDEFGH, но вместо этого использует 0-7. Вы не можете (легко) использовать 0-9, потому что 0-9 – до 4 бит, но не полностью 4 бита. Вот что делает его паршивым кодированием для двоичных данных.

Очень простой пример – он представляет каждый входной байт как 3-значное десятичное число:

 function data2numbers ($data) { $out = ""; for ($i = 0; $i < strlen ($data); $i++) { $out .= sprintf ("%03d", ord ($data[$i])); } return $out; } 

Недостатком является то, что он увеличивает размер любых входных данных (каждый входной байт представляется в виде трех выходных байтов).

Функция декодирования остается в качестве упражнения для читателя;)

Независимо от того, как вы кодируете, вы всегда окажетесь на небольшой базе. Может быть возможно уменьшить размер результирующего целого числа с меньшим количеством конверсий dechex (), но в конечном итоге вы сохраните несколько символов. При этом число действительно возбуждает момент, когда вы начинаете представлять многобайтные символы с 0-9.

Я должен задаться вопросом, не будут ли целые числа в виде идентификаторов, представляющих слова или полные строки, меньшим размером. На самом деле это не прямая кодировка, а жизнеспособный вариант.

@ el.pescado получает кредит в первом тайме, но он бросил вызов читателю. Поэтому я ответил (в основном потому, что хотел понять, что происходит).

 function pekka_encode($s) { $out = ''; for ($i=0;$i<strlen($s); $i++) { $out .= sprintf("%03d", ord($s[$i])); } return $out; } function pekka_decode($s) { $out = ''; for ($i=0;$i<strlen($s);$i+=3) { $out .= chr($s[$i].$s[$i+1].$s[$i+2]); } return $out; }