001 package biweekly.util; 002 003 /** 004 * Encodes and decodes data into base64. 005 * @author <a href="http://stackoverflow.com/users/518568/georgek">GeorgeK</a> 006 * @see <a 007 * href="http://stackoverflow.com/a/4265472/13379">http://stackoverflow.com/a/4265472/13379</a> 008 */ 009 public class Base64 { 010 private static final char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); 011 private static final int[] toInt = new int[128]; 012 static { 013 for (int i = 0; i < ALPHABET.length; i++) { 014 toInt[ALPHABET[i]] = i; 015 } 016 } 017 018 /** 019 * Translates the specified byte array into Base64 string. 020 * @param buf the byte array 021 * @return the translated Base64 string 022 */ 023 public static String encode(byte[] buf) { 024 int size = buf.length; 025 char[] ar = new char[((size + 2) / 3) * 4]; 026 int a = 0; 027 int i = 0; 028 while (i < size) { 029 byte b0 = buf[i++]; 030 byte b1 = (i < size) ? buf[i++] : 0; 031 byte b2 = (i < size) ? buf[i++] : 0; 032 033 int mask = 0x3F; 034 ar[a++] = ALPHABET[(b0 >> 2) & mask]; 035 ar[a++] = ALPHABET[((b0 << 4) | ((b1 & 0xFF) >> 4)) & mask]; 036 ar[a++] = ALPHABET[((b1 << 2) | ((b2 & 0xFF) >> 6)) & mask]; 037 ar[a++] = ALPHABET[b2 & mask]; 038 } 039 switch (size % 3) { 040 case 1: 041 ar[--a] = '='; 042 case 2: 043 ar[--a] = '='; 044 } 045 return new String(ar); 046 } 047 048 /** 049 * Translates the specified Base64 string into a byte array. 050 * @param s the Base64 string 051 * @return the byte array 052 */ 053 public static byte[] decode(String s) { 054 int delta = s.endsWith("==") ? 2 : s.endsWith("=") ? 1 : 0; 055 byte[] buffer = new byte[s.length() * 3 / 4 - delta]; 056 int mask = 0xFF; 057 int index = 0; 058 for (int i = 0; i < s.length(); i += 4) { 059 int c0 = toInt[s.charAt(i)]; 060 int c1 = toInt[s.charAt(i + 1)]; 061 buffer[index++] = (byte) (((c0 << 2) | (c1 >> 4)) & mask); 062 if (index >= buffer.length) { 063 return buffer; 064 } 065 int c2 = toInt[s.charAt(i + 2)]; 066 buffer[index++] = (byte) (((c1 << 4) | (c2 >> 2)) & mask); 067 if (index >= buffer.length) { 068 return buffer; 069 } 070 int c3 = toInt[s.charAt(i + 3)]; 071 buffer[index++] = (byte) (((c2 << 6) | c3) & mask); 072 } 073 return buffer; 074 } 075 076 private Base64() { 077 //hide 078 } 079 }