聊聊base62与tinyURL

可访问
• 阅读 16729

base64大家肯定是很熟悉了,那base62是什么东东,它常被用来做短url的映射。

ascii编码的62个字母数字

Value Encoding  Value Encoding  Value Encoding  Value Encoding
  0 a            17 r            34 I            51 Z
  1 b            18 s            35 J            52 0
  2 c            19 t            36 K            53 1
  3 d            20 u            37 L            54 2
  4 e            21 v            38 M            55 3
  5 f            22 w            39 N            56 4
  6 g            23 x            40 O            57 5
  7 h            24 y            41 P            58 6
  8 i            25 z            42 Q            59 7
  9 j            26 A            43 R            60 8
 10 k            27 B            44 S            61 9
 11 l            28 C            45 T
 12 m            29 D            46 U
 13 n            30 E            47 V
 14 o            31 F            48 W
 15 p            32 G            49 X
 16 q            33 H            50 Y

26个小写字母+26个大写字母+10个数字=62

    public static final String BASE_62_CHAR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    public static final int BASE = BASE_62_CHAR.length();

62进制与十进制的映射

62进制转10进制

还记得二进制转十进制的算法么,从右到左用二进制的每个数去乘以2的相应次方,次方要从0开始。62进制转10进制也类似,从右往左每个数*62的N次方,N从0开始。

    public static long toBase10(String str) {
        //从右边开始
        return toBase10(new StringBuilder(str).reverse().toString().toCharArray());
    }

    private static long toBase10(char[] chars) {
        long n = 0;
        int pow = 0;
        for(char item: chars){
            n += toBase10(BASE_62_CHAR.indexOf(item),pow);
            pow++;
        }
        return n;
    }

    private static long toBase10(int n, int pow) {
        return n * (long) Math.pow(BASE, pow);
    }

十进制转62进制

还记得十进制转二进制的算法么,除二取余,然后倒序排列,高位补零。转62进制也类似,不断除以62取余数,然后倒序。

    public static String fromBase10(long i) {
        StringBuilder sb = new StringBuilder("");
        if (i == 0) {
            return "a";
        }
        while (i > 0) {
            i = fromBase10(i, sb);
        }
        return sb.reverse().toString();
    }

    private static long fromBase10(long i, final StringBuilder sb) {
        int rem = (int)(i % BASE);
        sb.append(BASE_62_CHAR.charAt(rem));
        return i / BASE;
    }

短url的转换

主要思路,维护一个全局自增的id,每来一个长url,将其与一个自增id绑定,然后利用base62将该自增id转换为base62字符串,即完成转换。

public class Base62UrlShorter {

    private long autoIncrId = 10000;

    Map<Long, String> longUrlIdMap = new HashMap<Long, String>();

    public long incr(){
        return autoIncrId ++ ;
    }

    public String shorten(String longUrl){
        long id = incr();
        //add to mapping
        longUrlIdMap.put(id,longUrl);
        return Base62.fromBase10(id);
    }

    public String lookup(String shortUrl){
        long id = Base62.toBase10(shortUrl);
        return longUrlIdMap.get(id);
    }
}

测试

    @Test
    public void testLongUrl2Short(){
        Base62UrlShorter shorter= new Base62UrlShorter();
        String longUrl = "https://movie.douban.com/subject/26363254/";
        String shortUrl = shorter.shorten(longUrl);
        System.out.println("short url:"+shortUrl);
        System.out.println(shorter.lookup(shortUrl));
    }

关于容量

自增id为long型,最大2^64 -1

doc

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
3年前
typeScript数据类型
//布尔类型letisDone:booleanfalse;//数字类型所有数字都是浮点数numberletdecLiteral:number6;lethexLiteral:number0xf00d;letbinaryLiteral:number0b101
Stella981 Stella981
3年前
Kerberos无约束委派的攻击和防御
 0x00前言简介当ActiveDirectory首次与Windows2000Server一起发布时,Microsoft就提供了一种简单的机制来支持用户通过Kerberos对Web服务器进行身份验证并需要授权用户更新后端数据库服务器上的记录的方案。这通常被称为Kerberosdoublehopissue(双跃点问题),
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
Java base64编码解码工具类
前几天无意中看到Java中有Base64编码,不解的我去百科了一下,了解了Base64的基本使用和实现原理,于是在空暇时自己手动写了一个,这个类可以完成对字母数字的编码和解码工作,但是对于中文,还没有仔细研究其编码的实现过程。至于什么是Base64,用它来干什么,请移步到:http://zh.wikipedia.org/zhcn/Base64(http
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
JS汉字编码 (ascii,unicode)的转换与反转
ASCII就是编码英文的26个字母和一些常见的符号,之后扩展了一半。总之是一个字节来做编码,大于128的部分是一些特殊符号。但ASCII是无法编码别的东西的,比如说是不存在“中文的ascii码需要2个字符”这种说法的。ASCII就只有一个字节。Unicode是足够编码地球上所有的语言了,所以ASCII中所能表示的,Unicode当然全部包
Wesley13 Wesley13
3年前
Html5 FileReader 对文件进行Base64编码
以Base64进行编码的数据Url开始越来越广泛的被应用起来,原来做Base64转换要自己写一个小程序来转,其实Html5的FileReader的readAsDataURL方法读取出的数据就已经是Base64数据格式的Url了,利用FileReader实现一个对本地文件进行读取并且转换为Base64Url的页面也非常简单。页面地址:http://z
Stella981 Stella981
3年前
Linux应急响应(一):SSH暴力破解
0x00前言SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议,主要用于给远程登录会话数据进行加密,保证数据传输的安全。SSH口令长度太短或者复杂度不够,如仅包含数字,或仅包含字母等,容易被攻击者破解,一旦被攻击者获取,可用来直接登录系统,控制服务器所有权限。0x01应急场景某天,网站