我想创建一个URL缩短服务,你可以写一个长URL到输入字段和服务缩短URL为“http://www.example.org/abcdef”。

可以用包含a-z, a-z和0-9的6个字符的字符串代替"abcdef"。这样就有560 ~ 570亿个可能的字符串。

我的方法:

我有一个有三列的数据库表:

Id,整数,自动递增 long, string,用户输入的长URL 短,字符串,缩短的URL(或只有六个字符)

然后将长URL插入到表中。然后,我将为“id”选择自动递增的值,并构建它的散列。这个散列应该作为“short”插入。但是我应该构建什么样的哈希呢?像MD5这样的哈希算法会创建太长的字符串。我认为我不用这些算法。一个自建的算法也可以。

我的想法:

对于“http://www.google.de/”,我得到了自动增量id 239472。然后我执行以下步骤:

short = '';
if divisible by 2, add "a"+the result to short
if divisible by 3, add "b"+the result to short
... until I have divisors for a-z and A-Z.

可以不断重复,直到这个数不能被整除为止。你认为这是一个好方法吗?你有更好的主意吗?

由于对这个主题的持续兴趣,我已经发布了一个高效的GitHub解决方案,包括JavaScript、PHP、Python和Java的实现。如果你喜欢,添加你的解决方案:)


当前回答

我有一个问题的变体,因为我存储了来自许多不同作者的网页,需要防止通过猜测发现页面。所以我的短url在Base-62字符串中添加了几个额外的数字作为页码。这些额外的数字是由页面记录本身的信息生成的,它们确保3844个url中只有一个是有效的(假设2位Base-62)。您可以在http://mgscan.com/MBWL上看到概要描述。

其他回答

public class TinyUrl {
    
        private final String characterMap = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        private final int charBase = characterMap.length();
    
        public String covertToCharacter(int num){
            StringBuilder sb = new StringBuilder();
    
            while (num > 0){
                sb.append(characterMap.charAt(num % charBase));
                num /= charBase;
            }
    
            return sb.reverse().toString();
        }
    
        public int covertToInteger(String str){
            int num = 0;
            for(int i = 0 ; i< str.length(); i++)
                num += characterMap.indexOf(str.charAt(i)) * Math.pow(charBase , (str.length() - (i + 1)));
    
            return num;
        }
}
    
class TinyUrlTest{
    
    public static void main(String[] args) {
        TinyUrl tinyUrl = new TinyUrl();
        int num = 122312215;
        String url = tinyUrl.covertToCharacter(num);
        System.out.println("Tiny url:  " + url);
        System.out.println("Id: " + tinyUrl.covertToInteger(url));
    }
}

为什么要使用哈希呢?

您只需将自动递增值简单地转换为字母数字值。你可以通过使用一些基数转换很容易做到这一点。假设您的字符空间(a-z, a-z, 0-9等)有62个字符,将id转换为以40为基数的数字并使用这些字符作为数字。

下面是一个Node.js实现,可能是bit.ly。生成一个高度随机的七字符字符串。

它使用Node.js加密生成高度随机的25个字符集,而不是随机选择7个字符。

var crypto = require("crypto");
exports.shortURL = new function () {
    this.getShortURL = function () {
        var sURL = '',
            _rand = crypto.randomBytes(25).toString('hex'),
            _base = _rand.length;
        for (var i = 0; i < 7; i++)
            sURL += _rand.charAt(Math.floor(Math.random() * _rand.length));
        return sURL;
    };
}

为什么不直接将id转换为字符串呢?您只需要一个函数将0到61之间的数字映射到单个字母(大写/小写)或数字。然后应用它来创建,比如说,4个字母的代码,你就有了1470万个url。

您可以散列整个URL,但如果您只想缩短id,请按照marcel的建议进行。我写了这个Python实现:

https://gist.github.com/778542