开发者

Modified Base 64 for URLs, or Custom/Arbitrary "Base" based on custom alphabet, in PHP

I've searched around, but after sifting through quite a lot of posts, I haven't really seen this covered --开发者_JAVA百科

I'd like to convert an unsigned, base-10 integer to a much higher "custom" base, by providing the "alphabet", but I'm not sure where to start, and am probably overlooking the simplicity.

As mentioned on wikipedia, there are variants of traditional Base 64 that do not add padding, etc., for use in URLs and what-not, but I am not sure how to begin implementing that. 8 I'm not encoding strings or binary data - just plain integer numbers - and would like to be able to feed an arbitrarily-long "alphabet" into the conversion function. Ideally, of course, I would be able to reverse the numbers as well.

I'm using PHP, but I should be able to work with anything using straightforward math and not a lot of custom libraries, of course.


On this article, you can find a function to exactly what you ask (Look at the "Creating a super-compressed URL" section) : Building a URL Shortener

Basically, that function :

  • Encodes an integer,
  • Allows you to use whatever alphabet you want

And there is a reverse function just below ;-)


I coded a function to do exactly this for phunction, here is the stand-alone version:

function Base($number, $input, $output, $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
{
    if (strlen($charset) >= 2)
    {
        $input = max(2, min($input, strlen($charset)));
        $output = max(2, min($output, strlen($charset)));
        $number = ltrim(preg_replace('~[^' . preg_quote(substr($charset, 0, $input), '~') . ']+~', '', $number), $charset[0]);

        if (strlen($number) > 0)
        {
            if ($input != 10)
            {
                $result = 0;

                foreach (str_split(strrev($number)) as $key => $value)
                {
                    $result += pow($input, $key) * intval(strpos($charset, $value));
                }

                $number = $result;
            }

            if ($output != 10)
            {
                $result = $charset[$number % $output];

                while (($number = floor($number / $output)) > 0)
                {
                    $result = $charset[$number % $output] . $result;
                }

                $number = $result;
            }

            return $number;
        }

        return $charset[0];
    }

    return false;
}

Here is how you can use it:

var_dump(Base(1000, 10, 62)); // g8
var_dump(Base('g8', 62, 10)); // 1000

var_dump(Base(14776336, 10, 62)); // 10000
var_dump(Base('10000', 62, 10)); // 14776336

By default I'm using a base 62 charset but you can change this to fit your needs.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜