将字符串转换为数字再转换为字符串?

8
我想了解如何将短的ASCII字符串转换为数字(int、float或数字字符串)。我看到这里的帖子中提到了完美哈希,似乎是我需要的。然而,我对此的数学理解还不够。 你如何将ASCII字符串转换为数字序列,然后再转回字符串? 顺便说一句,将字符串分解为其ASCII字符数字很容易。
foreach(str_split($string) as $char) $number .= ord($char);

更新

经过更多阅读,我得出了这个结论。但是,我想知道有没有办法缩短数字序列,使它不那么长。

class intnum
{
    public static $charset = array(
        32 => ' ', 33 => '!', 34 => '"', 35 => '#', 36 => '$',
        37 => '%', 38 => '&', 39 => "'", 40 => '(', 41 => ')',
        42 => '*', 43 => '+', 44 => ',', 45 => '-', 46 => '.',
        47 => '/', 48 => '0', 49 => '1', 50 => '2', 51 => '3',
        52 => '4', 53 => '5', 54 => '6', 55 => '7', 56 => '8',
        57 => '9', 58 => ':', 59 => ';', 60 => '<', 61 => '=',
        62 => '>', 63 => '?', 64 => '@', 65 => 'A', 66 => 'B',
        67 => 'C', 68 => 'D', 69 => 'E', 70 => 'F', 71 => 'G',
        72 => 'H', 73 => 'I', 74 => 'J', 75 => 'K', 76 => 'L',
        77 => 'M', 78 => 'N', 79 => 'O', 80 => 'P', 81 => 'Q',
        82 => 'R', 83 => 'S', 84 => 'T', 85 => 'U', 86 => 'V',
        87 => 'W', 88 => 'X', 89 => 'Y', 90 => 'Z', 91 => '[',
        92 => '\\', 93 => ']', 94 => '^', 95 => '_', 96 => '`',
        97 => 'a', 98 => 'b', 99 => 'c', 100 => 'd', 101 => 'e',
        102 => 'f', 103 => 'g', 104 => 'h', 105 => 'i', 106 => 'j',
        107 => 'k', 108 => 'l', 109 => 'm', 110 => 'n', 111 => 'o',
        112 => 'p', 113 => 'q', 114 => 'r', 115 => 's', 116 => 't',
        117 => 'u', 118 => 'v', 119 => 'w', 120 => 'x', 121 => 'y',
        122 => 'z', 123 => '{', 124 => '|', 125 => '}'
    );

    public static function fromNumber($number)
    {
        $string = '';
        while($number)
        {
            $value = substr($number, 0, 2);
            $number = substr($number, 2);

            if($value < 32)
            {
                $value .= substr($number, 0, 1);
                $number = substr($number, 1);
            }

            $string .= self::$charset[ (int) $value];
        }
        return $string;
    }

    public static function fromString($string)
    {
        $number = '';
        foreach(str_split($string) as $char) $number .= ord($char);
        return $number;
    }
}

$string = 'this is my test string to convert';

$number = intnum::fromString($string);
$string = intnum::fromNumber($number);

为什么不使用您刚刚发布的代码? - Brad
@Brad,我该怎么把字符串取回来? - Xeoncross
3个回答

14
一个将字符串转换为数字的一行代码编码器(PHP 5.3风格):
$numbers = implode(array_map(function ($n) { return sprintf('%03d', $n); },
                          unpack('C*', $str)));

它只是将每个字节转换为其十进制数等效值,将其补零到一个固定长度的3位数字,以便可以明确地转换回去。

解码器将其转换回字符串:

$str = implode(array_map('chr', str_split($numbers, 3)));

示例文本:

适用于所有字符串
087195182114107115032119195173116104032097108108032227130185227131136227131170227131179227130176227130186


嗯,似乎无法处理您提供的Unicode字符。 - Xeoncross
只要您确保以与输入相同的编码解释结果,它就可以正常工作。 - deceze
请查看 http://codepad.org/wXA9ViFu (使用 PHP 5.2 格式编写,因为 Codepad 尚不支持 5.3)。 - deceze
能在 PHP 8 中运行吗? - xyzcodeeee

2

你不能只把字符转换成数字字符串并期望它能还原,因为有些字符可能由两个数字组成,而其他字符则可能由三个数字组成。

例如:

Kang-HO将给你:10797106103457279

现在你怎么知道它不是:10-79-71-0-61-0-34-57-27-9?

你需要将所有数字都填充到3位数代码中,这样就可以得到:107097106103045072079,然后将其分解成3个数字的块,并将其ASC编码还原回来...


@PhilLello,你看到有没有办法使用十六进制修改我上面的代码? - Xeoncross

0

如果你想将字符串转换为一系列整数,你必须始终使用固定的数字块。在这种情况下,由于ASCII使用8位字,因此最大可能的整数是2^8-1 = 255。

你应该用0填充未使用的空间:

function zero_fill($num){
    if($num <= 9) $num = "00".$num;
    elseif($num <= 99) $num = "0".$num;
    return $num;
}

你可以将你创建的函数与此函数结合使用,要恢复字符串,请取出每个由 3 个整数组成的块,并将它们转换回对应的 ASCII 字符。
foreach(str_split($numberSeq, 3) as $asciiIntValue) $stringBack .= chr($asciiIntValue);

"11位元组词"? 2^11-1 = 127? 我认为你有点跑题了。 - deceze
本来也要写的,2^11 = 2048... 你可能是指的 2^7,但是 ASCII 码有 255 个字符,所以应该是 2^8... - Mathieu Dumoulin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接