How to make shorten url using BASE62
How to make shorten url using BASE62.
짧은 URL을 만들기 위한 알고리즘을 고민하던 중. base64를 고민해봤는데, 보통의 Short URL들의 특징을 살펴보니 특수문자를 제외한 영문 대소문자 + 숫자로만 이루어진 조합의 URL을 사용하고 있다. 특수문자가 사용될 경우 URL Encoding을 해줘야 하기때문에 (Base64의 +의 경우 %2D, /의 경우 %2F, 패딩 '='은 %03D) 특수 문자를 제외한 나머지 62개의 값을 가지고 URL을 생성을 목적으로 하는게 Base62의 기본 알고리즘이다.
기본적으로 Base64의 알고리즘을 알 필요가 있다.
Base64는 8비트로 구성된 입력값을 2의 6승인 6비트씩 짤라서 64까지의 값을 표현 한다.
ASCII Code 입력 값 : CBA 인코딩
01000011 |
01000010 |
01000001 |
|
010000 |
110100 |
001001 |
000001 |
Q |
0 |
J |
B |
Base64 Encoding 결과 값 : Q0JB
Base62의 경우에는 +,/ 문자를 제외한 62개의 값을 표현한다.
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
특정 sequence를 매칭하여 BASE62 주소로 반환하는 코드를 작성해보았다.
int형과 long 타입까지 생성 가능하도록 작성 하였다.
Base62.java
/** * Created by rocksea on 2016. 5. 12. */ public class Base62 { /** * Base62 Character Table */ static final char[] BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray(); /** * Base62 Encoding * * @return the base 62 string of an integer */ public static String encode(int value) { final StringBuilder sb = new StringBuilder(); do { int i = value % 62; sb.append(BASE62[i]); value /= 62; } while (value > 0); return sb.toString(); } public static String encodeToLong(long value) { final StringBuilder sb = new StringBuilder(); do { int i = (int)(value % 62); sb.append(BASE62[i]); value /= 62; } while (value > 0); return sb.toString(); } /** * Returns the base 62 value of a string. * * @return the base 62 value of a string. */ public static int decode(String value) { int result=0; int power=1; for (int i = 0; i < value.length(); i++) { int digit = new String(BASE62).indexOf(value.charAt(i)); result += digit * power; power *= 62; } return result; } public static long decodeToLong(String value) { long result=0; long power=1; for (int i = 0; i < value.length(); i++) { int digit = new String(BASE62).indexOf(value.charAt(i)); result += digit * power; power *= 62; } return result; } }
Base62Test.java
import org.junit.Test; import java.util.Random; import static junit.framework.Assert.assertEquals; public class Base62Test { @Test public void testEncodeAndDecode() throws Exception{ String encodedReservationNo = Base62.encodeToLong(1234512345); System.out.println("ENCODE : "+encodedReservationNo+", DECODE : " + Base62.decodeToLong(encodedReservationNo)); assertEquals(1234512345, Base62.decodeToLong(encodedReservationNo)); } @Test public void testRandomEncodeAndDecode() throws Exception{ for(int i=0; i < 10; i++) { Random rnd = new Random(); long value = Math.abs(rnd.nextLong() % 10000000000L); System.out.println("VALUE : " + value); String encodedReservationNo = Base62.encodeToLong(value); System.out.println("ORIGINAL : " + value + ", ENCODE : " + encodedReservationNo + ", DECODE : " + Base62.decodeToLong(encodedReservationNo)); assertEquals(value, Base62.decodeToLong(encodedReservationNo)); } } }
SMS나 메세지, SNS URL 공유가 많이 필요한 서비스에 활용할 경우 유용하다.