You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
4.2 KiB
161 lines
4.2 KiB
11 years ago
|
package de.timroes.base64;
|
||
|
|
||
|
import java.util.HashMap;
|
||
|
|
||
|
/**
|
||
|
* A Base64 en/decoder. You can use it to encode and decode strings and byte arrays.
|
||
|
*
|
||
|
* @author Tim Roes
|
||
|
*/
|
||
|
public class Base64 {
|
||
|
|
||
|
private static final char[] code = ("=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||
|
+ "abcdefghijklmnopqrstuvwxyz0123456789+/").toCharArray();
|
||
|
|
||
|
private static final HashMap<Character,Byte> map = new HashMap<Character, Byte>();
|
||
|
|
||
|
static {
|
||
|
for(int i = 0; i < code.length; i++) {
|
||
|
map.put(code[i], (byte)i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Decode a base64 encoded string to a byte array.
|
||
|
*
|
||
|
* @param in A string representing a base64 encoding.
|
||
|
* @return The decoded byte array.
|
||
|
*/
|
||
|
public static byte[] decode(String in) {
|
||
|
|
||
|
in = in.replaceAll("\\r|\\n","");
|
||
|
if(in.length() % 4 != 0) {
|
||
|
throw new IllegalArgumentException("The length of the input string must be a multiple of four.");
|
||
|
}
|
||
|
|
||
|
if(!in.matches("^[A-Za-z0-9+/]*[=]{0,3}$")) {
|
||
|
throw new IllegalArgumentException("The argument contains illegal characters.");
|
||
|
}
|
||
|
|
||
|
byte[] out = new byte[(in.length()*3)/4];
|
||
|
|
||
|
char[] input = in.toCharArray();
|
||
|
|
||
|
int outi = 0;
|
||
|
int b1, b2, b3, b4;
|
||
|
for(int i = 0; i < input.length; i+=4) {
|
||
|
b1 = (map.get(input[i]) - 1);
|
||
|
b2 = (map.get(input[i+1]) - 1);
|
||
|
b3 = (map.get(input[i+2]) - 1);
|
||
|
b4 = (map.get(input[i+3]) - 1);
|
||
|
out[outi++] = (byte)(b1 << 2 | b2 >>> 4);
|
||
|
out[outi++] = (byte)((b2 & 0x0F) << 4 | b3 >>> 2);
|
||
|
out[outi++] = (byte)((b3 & 0x03) << 6 | (b4 & 0x3F));
|
||
|
}
|
||
|
|
||
|
if(in.endsWith("=")) {
|
||
|
byte[] trimmed = new byte[out.length - (in.length() - in.indexOf("="))];
|
||
|
System.arraycopy(out, 0, trimmed, 0, trimmed.length);
|
||
|
return trimmed;
|
||
|
}
|
||
|
|
||
|
return out;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Decode a base64 encoded string to a string.
|
||
|
*
|
||
|
* @param in The string representation of the base64 encoding.
|
||
|
* @return The decoded string in the default charset of the JVM.
|
||
|
*/
|
||
|
public static String decodeAsString(String in) {
|
||
|
return new String(decode(in));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Encode a String and return the encoded string.
|
||
|
*
|
||
|
* @param in A string to encode.
|
||
|
* @return The encoded byte array.
|
||
|
*/
|
||
|
public static String encode(String in) {
|
||
|
return encode(in.getBytes());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Encode a Byte array and return the encoded string.
|
||
|
*
|
||
|
* @param in A string to encode.
|
||
|
* @return The encoded byte array.
|
||
|
*/
|
||
|
public static String encode(Byte[] in) {
|
||
|
byte[] tmp = new byte[in.length];
|
||
|
for(int i = 0; i < tmp.length; i++) {
|
||
|
tmp[i] = in[i];
|
||
|
}
|
||
|
return encode(tmp);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Encode a byte array and return the encoded string.
|
||
|
*
|
||
|
* @param in A string to encode.
|
||
|
* @return The encoded byte array.
|
||
|
*/
|
||
|
public static String encode(byte[] in) {
|
||
|
StringBuilder builder = new StringBuilder(4 * ((in.length+2)/3));
|
||
|
byte[] encoded = encodeAsBytes(in);
|
||
|
for(int i = 0; i < encoded.length; i++) {
|
||
|
builder.append(code[encoded[i]+1]);
|
||
|
if(i % 72 == 71)
|
||
|
builder.append("\n");
|
||
|
}
|
||
|
return builder.toString();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Encode a String and return the encoded byte array. Bytes that has been
|
||
|
* appended to pad the string to a multiple of four are set to -1 in the array.
|
||
|
*
|
||
|
* @param in A string to encode.
|
||
|
* @return The encoded byte array.
|
||
|
*/
|
||
|
public static byte[] encodeAsBytes(String in) {
|
||
|
return encodeAsBytes(in.getBytes());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Encode a byte array and return the encoded byte array. Bytes that has been
|
||
|
* appended to pad the string to a multiple of four are set to -1 in the array.
|
||
|
*
|
||
|
* @param inArray A string to encode.
|
||
|
* @return The encoded byte array.
|
||
|
*/
|
||
|
public static byte[] encodeAsBytes(byte[] inArray) {
|
||
|
|
||
|
// Output string must be 4 * floor((n+2)/3) large
|
||
|
byte[] out = new byte[4 * ((inArray.length+2)/3)];
|
||
|
// Create padded input array with the next largest length that is a multiple of 3
|
||
|
byte[] in = new byte[(inArray.length+2)/3*3];
|
||
|
// Copy content form unpadded to padded array
|
||
|
System.arraycopy(inArray, 0, in, 0, inArray.length);
|
||
|
|
||
|
int outi = 0;
|
||
|
for(int i = 0; i < in.length; i+=3) {
|
||
|
|
||
|
out[outi++] = (byte)((in[i] & 0xFF) >>> 2);
|
||
|
out[outi++] = (byte)(((in[i] & 0x03) << 4) | ((in[i+1] & 0xFF) >>> 4));
|
||
|
out[outi++] = (byte)(((in[i+1] & 0x0F) << 2) | ((in[i+2] & 0xFF) >>> 6));
|
||
|
out[outi++] = (byte)(in[i+2] & 0x3F);
|
||
|
|
||
|
}
|
||
|
|
||
|
for(int i = in.length - inArray.length; i > 0; i--) {
|
||
|
out[out.length - i] = -1;
|
||
|
}
|
||
|
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
}
|