是否存在编码和解码任意数据的常用方法,因此编码的最终结果仅包含数字 - 如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"
答案 0 :(得分:12)
您可以将(单字节字符)字符串视为基本256编码的数字,其中“\ x00”表示0,''(空格,即“\ x20”)表示32,依此类推,直到“\ xFF “,代表255。
仅使用数字0-9的表示可以通过将表示更改为基数10来完成。
请注意,“base64编码”实际上不是base conversion。 base64将输入分成3个字节(24位)的组,并分别对这些组进行基本转换。这很有效,因为24位的数字可以用基数64中的四位数表示(2 ^ 24 = 64 ^ 4)。
这或多或少是el.pescado的作用 - 他将输入数据分成8位,然后将数字转换为基数10.然而,这种技术相对于基数为64的编码有一个缺点 - 它确实未与字节边界正确对齐。要表示一个8位的数字(无符号时为0-255),我们需要基数为10的三位数。但是,最左边的数字比其他数字的信息少。它可以是0,1或2(对于无符号数)。
基数10中的数字存储log(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 Mary had a little lamb
由于每个数字仅编码log(10)/log(2)=~3.32193
位,因此预计该数字往往为140% longer(不会超过200%,与el.pescado的回答一样)。
答案 1 :(得分:7)
那么,那将是“基本8”编码而不是Base 64.这更好地称为Octal。
所有Base64都将比特流转换为6比特块(0-63),并从64个字符的字符集中分配一个字符。 Octal使用3位,0-7。所以它可以使用ABCDEFGH,而是使用0-7。您不能(轻松)使用0-9,因为0-9最多为4位,但不完全是4位。这就是使它成为二进制数据的糟糕编码的原因。
答案 2 :(得分:2)
非常简单的例子 - 它将每个输入字节表示为3位十进制数字:
function data2numbers ($data) {
$out = "";
for ($i = 0; $i < strlen ($data); $i++) {
$out .= sprintf ("%03d", ord ($data[$i]));
}
return $out;
}
下行是它将任何输入数据的大小增加三倍(每个输入字节表示为三个输出字节)。
解码功能留给读者练习;)
答案 3 :(得分:2)
无论你如何编码,你总是会以更小的基数结束。通过一些dechex()转换可以缩小结果整数,但最终只能保存几个字符。话虽这么说,当你开始用0-9表示多字节字符时,这个数字真的会气球。
我不得不想知道整数是ID,代表单词还是完整字符串,不会提供更小的占用空间。不是真正的直接编码,而是可行的选择。
@ 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;
}