以4个32位整数存储字母数字字符串

时间:2015-07-24 21:17:01

标签: php encoding binary

继上一个问题here之后,如何重构以下(可怕但工作正常的POC)代码只支持0到2147483647之间的整数?

<?php   
$lower = 'abcdefghijklmnopqrstuvwxyz';
$upper = strtoupper($lower);
$numbers = '1234567890';
$chars = $upper.$lower.$numbers;

$map = [];
for ($i = 1; $i <= strlen($chars); $i++) {
    $map[$chars{$i - 1}] = $i;
}
$map[' '] = count($map) + 1;

function map($char)
{
    global $map;

    return $map[$char];
}

function encode($char)
{
    global $map;

    return sprintf('%06s', decbin($map[$char]));
}

function bytesToInt(array $bytes)
{
    $bytes = array_values($bytes);

    $int = (int) ($bytes[3]<<24) | ($bytes[2]<<16) | ($bytes[1]<<8) | ($bytes[0]);

    if ($int >= 2147483648) {
        $int -= 4294967296;
    }

    return $int;
}

$message = $argv[1];
$length = strlen($message);

if ($length > 21) {
    die('nope');
}

echo 'Encoding "'.$message.'" which is '.$length.' bytes long'."\n";

$max = 128;

$joined = '';
for ($i = 0; $i < $length; $i++) {
    $joined .= encode($message{$i});
}

$length = strlen($joined);
$joined .= str_repeat('0', $max - $length);
$length = strlen($joined);

echo $joined."\n";

$bytes = [];
$position = 0;
$bits = 8;

while ($position < $max) {
    $byte = substr($joined, $position, $bits);
    $bytes[] = bindec($byte);
    $position += $bits;
}

print_r($bytes);

$joined = '';
for ($i = 0; $i < 16; $i += 4) {
    $int = bytesToInt(array_slice($bytes, $i, 4))."\n";

    echo "Int: {$int}\n";
    $back = unpack("C*", pack("L", $int));
    print_r($back);

    foreach ($back as $byte) {
        $joined .= sprintf('%08s', decbin($byte));
    }
}

echo $joined."\n";

$map = array_flip($map);
print_r($map);
$position = 0;
$message = '';
while ($position < $max) {
    $dec = bindec(substr($joined, $position, 6));
    if ($dec === 0) {
        break;
    }
    $char = $map[$dec];
    $message .= $char;
    $position += 6;
}

echo $message."\n";

当前代码允许21个字符集[0-9A-za-z]编码为-2147483647和2147483647之间的整数。

我怀疑21个字符限制显然必须根据新要求减少到10或11个字符,这对我的用例来说是令人满意的。

1 个答案:

答案 0 :(得分:0)

对不起,但是代码太多了。

不仅仅是针对这个问题,但如果您在上一个问题中提到过您只需要在4位或32位整数中存储10或11个字母数字字符,那么您就不需要了一共编码为6个字节,如11&lt; 16。

只需将字符的ASCII值存储在字节数组中,然后将其转换为4个整数。

整数的最高有效位是符号位,它在设置(1)时使整数为负。使用字符的ASCII值,所有这些都将是&lt; 127,该位,值为128,永远不会被设置。