
1 import java.io.ByteArrayOutputStream; 2 import java.io.IOException; 3 import java.io.StringWriter; 4 import java.util.Arrays; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 public class MyBase64 { 9 private static final char[] set = ".0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" 10 .toCharArray(); 11 /* 12 * 结尾表示填充0x0字符数目 13 */ 14 static final char blank = '-'; 15 /* 16 * 间隔三个字符分段 17 */ 18 static final int step = 3; 19 /* 20 * 源数组结尾填0 21 */ 22 static final byte fill = 0x0; 23 24 private static MyBase64A myBase64 = null; 25 26 public static MyBase64A getInstance() { 27 if (myBase64 == null) { 28 synchronized (MyBase64A.class) { 29 if (myBase64 == null) { 30 myBase64 = new MyBase64A(); 31 } 32 } 33 } 34 return myBase64; 35 // return threadLocal.get(); 36 } 37 38 private static Map<Character, Integer> initMap() { 39 Map<Character, Integer> hashMap = new HashMap<Character, Integer>( 40 set.length); 41 for (int i = 0; i < set.length; i++) { 42 hashMap.put(set[i], i); 43 } 44 return hashMap; 45 } 46 47 private final Map<Character, Integer> map; 48 49 private MyBase64A() { 50 map = initMap(); 51 } 52 53 public byte[] reverseTrans(String string) throws IOException { 54 char[] chars = string.toCharArray(); 55 56 final int step = 4; 57 58 int approximation = chars.length * 3 / 4; 59 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream( 60 approximation); 61 62 long swap; 63 char c1, c2, c3, c4; 64 byte b1, b2, b3; 65 66 int begin = 0; 67 int end = chars.length; 68 69 int offset = begin; 70 while (offset + 3 < end) { 71 c1 = chars[offset]; 72 c2 = chars[offset + 1]; 73 c3 = chars[offset + 2]; 74 c4 = chars[offset + 3]; 75 76 swap = (map.get(c1) & 0xff) << 18 | (map.get(c2) & 0xff) << 12 77 | (map.get(c3) & 0xff) << 6 | (map.get(c4) & 0xff); 78 79 b1 = (byte) ((swap >> 16) & 0xff); 80 b2 = (byte) ((swap >> 8) & 0xff); 81 b3 = (byte) (swap & 0xff); 82 83 byteArrayOutputStream.write(b1); 84 byteArrayOutputStream.write(b2); 85 byteArrayOutputStream.write(b3); 86 87 offset += step; 88 } 89 // logger.debug(end - offset); 90 byte[] bytes = Arrays.copyOf(byteArrayOutputStream.toByteArray(), 91 byteArrayOutputStream.size() - (end - offset)); 92 return bytes; 93 } 94 95 /** 96 * 97 * @param source 98 * 总之是一个字节队列。 99 * @return url相容的 自制 base64编码 100 */ 101 public String trans(byte[] source) { 102 int begin = 0, end = source.length; 103 /* 104 * (source.length + 2) / 3 处以三,余数上限取整。 + 2 , 可能追加至多两个填充占位符。 105 */ 106 int approximation = (source.length + 2) / 3 * 4 + 2; 107 StringWriter stringWriter = new StringWriter(approximation); 108 109 int offset; 110 long swap; 111 byte a, b, c; 112 int num1, num2, num3, num4; 113 int app = 0; 114 115 offset = begin; 116 while (offset < end) { 117 a = source[offset]; 118 if (offset + 1 < end) { 119 b = source[offset + 1]; 120 } else { 121 b = fill; 122 app++; 123 } 124 if (offset + 2 < end) { 125 c = source[offset + 2]; 126 } else { 127 c = fill; 128 app++; 129 } 130 131 swap = ((a & 0xff) << 16) | ((b & 0xff) << 8) | c & 0xff; 132 133 // logger.debug(String.format("%x", swap)); 134 135 num1 = (int) ((swap >> 18) & 63); 136 num2 = (int) ((swap >> 12) & 63); 137 num3 = (int) ((swap >> 6) & 63); 138 num4 = (int) (swap & 63); 139 140 stringWriter.append(set[num1]); 141 stringWriter.append(set[num2]); 142 stringWriter.append(set[num3]); 143 stringWriter.append(set[num4]); 144 145 offset += step; 146 } 147 if (app == 1) { 148 stringWriter.append(blank); 149 } 150 if (app == 2) { 151 stringWriter.append(blank); 152 stringWriter.append(blank); 153 } 154 return stringWriter.toString(); 155 } 156 }
结果可以作为url组件, 并且保持相同于源字节数组大小关系 (按从0偏移处比较, 鸡蛋大头开始, 不知道喜欢大头的多还是小头的多)。