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

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

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

$encoded = numbers_encode("Mary had a little lamb");

echo $encoded; // outputs e.g. 12238433742239423742322 (fictitious result)

$decoded = numbers_decode("12238433742239423742322");

echo $decoded; // outputs "Mary had a little lamb"
9
задан Pekka supports GoFundMonica 23 January 2011 в 12:59
поделиться

4 ответа

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

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

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

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

Цифра в базе 10 хранит лог (10) / лог (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
Mary had a little lamb

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

13
ответ дан 4 December 2019 в 08:50
поделиться

Ну, это была бы кодировка "base 8", а не Base 64. Это более известно как Octal.

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

7
ответ дан 4 December 2019 в 08:50
поделиться

Независимо от того, как вы кодируете, в итоге вы всегда получите меньшее основание. Возможно, удастся немного уменьшить полученное целое число с помощью преобразований 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;
}
2
ответ дан 4 December 2019 в 08:50
поделиться

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

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

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

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

2
ответ дан 4 December 2019 в 08:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: