Created
September 25, 2014 14:57
-
-
Save dragon66/0bbb076b6c21202ea958 to your computer and use it in GitHub Desktop.
Java Base64 encoder decoder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Copyright (c) 2014 by Wen Yu. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Any modifications to this file must keep this entire header intact. | |
*/ | |
package cafe.string; | |
import cafe.util.ArrayUtils; | |
/** | |
* A simple base64 encoding and decoding utility class. It can also | |
* encode and decode non ASII characters such as Chinese. | |
* <p> | |
* Changed decode method to remove potential problem when decoding | |
* concatenated encoded strings. | |
* | |
* @author Wen Yu, [email protected] | |
* @version 1.01 04/18/2012 | |
*/ | |
public final class Base64 | |
{ | |
private static final char[] base64Map = // base64 character table | |
{ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N', | |
'O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b', | |
'c','d','e','f','g','h','i','j','k','l','m','n','o','p', | |
'q','r','s','t','u','v','w','x','y','z','0','1','2','3', | |
'4','5','6','7','8','9','+','/' } ; | |
/** | |
* Convert the platform dependent string characters to UTF8 which can | |
* also be done by calling the java String method getBytes("UTF-8"), | |
* but I hope to do it from the ground up. | |
*/ | |
private static byte[] toUTF8ByteArray(String s) | |
{ | |
int ichar; | |
byte buffer[]=new byte[3*(s.length())]; | |
int index=0; | |
int count=0; // Count the actual bytes in the buffer array | |
for(int i=0;i<s.length();i++) | |
{ | |
ichar = s.charAt(i); | |
// Determine the bytes for a specific character | |
if((ichar>=0x0080)&(ichar<=0x07FF)) | |
{ | |
buffer[index++] = (byte)((6<<5)|((ichar>>6)&31)); | |
buffer[index++] = (byte)((2<<6)|(ichar&63)); | |
count+=2; | |
} | |
// Determine the bytes for a specific character | |
else if((ichar>=0x0800)&(ichar<=0x0FFFF)) | |
{ | |
buffer[index++] = (byte)((14<<4)|((ichar>>12)&15)); | |
buffer[index++] = (byte)((2<<6)|((ichar>>6)&63)); | |
buffer[index++] = (byte)((2<<6)|(ichar&63)); | |
count+=3; | |
} | |
// Determine the bytes for a specific character | |
else if((ichar>=0x0000)&(ichar<=0x007F)) | |
{ | |
buffer[index++] = (byte)((0<<7)|(ichar&127)); | |
count+=1; | |
} | |
// Longer than 16 bit Unicode is not supported | |
else throw new RuntimeException("Unsupported encoding character length!\n"); | |
} | |
return ArrayUtils.subArray(buffer, 0, count); // Trim to size | |
} | |
public static String encode(String s) | |
{ | |
byte buf[] = toUTF8ByteArray(s); | |
return encode(buf); | |
} | |
public static String encode(byte buf[]) | |
{ | |
StringBuffer sb = new StringBuffer(); | |
String padder = "" ; | |
if( buf.length == 0 ) return "" ; | |
// Cope with less than 3 bytes conditions at the end of buf | |
switch( buf.length%3) | |
{ | |
case 1 : | |
{ | |
padder += base64Map[(( buf[buf.length-1] >>> 2 ) & 63) ] ; | |
padder += base64Map[ (( buf[buf.length-1] << 4 ) & 63) ] ; | |
padder += "==" ; | |
break ; | |
} | |
case 2 : | |
{ | |
padder += base64Map[ ( buf[buf.length-2] >>> 2 ) & 63 ] ; | |
padder += base64Map[ (((buf[buf.length-2] << 4 )&63)) | ((( buf[buf.length-1] >>>4 ) & 63)) ] ; | |
padder += base64Map[ ( buf[buf.length-1] << 2 ) & 63 ] ; | |
padder += "=" ; | |
break ; | |
} | |
default : break ; | |
} | |
int temp =0 ; | |
int index = 0 ; | |
// Encode buf.length-buf.length%3 bytes which must be a multiply of 3 | |
for( int i=0 ; i < ( buf.length-(buf.length % 3) ) ; ) | |
{ | |
// Get three bytes and encode them to four base64 characters | |
temp = ((buf[i++] << 16)&0xFF0000)|((buf[i++] << 8)&0xFF00)|(buf[i++]&0xFF) ; | |
index = (temp >> 18) & 63 ; | |
sb.append(base64Map[ index ]); | |
if(sb.length()%76==0)// A Base64 encoded line is no longer than 76 characters | |
sb.append('\n'); | |
index = (temp >> 12 ) & 63 ; | |
sb.append(base64Map[ index ]); | |
if(sb.length()%76==0) | |
sb.append('\n'); | |
index = (temp >> 6 ) & 63 ; | |
sb.append(base64Map[ index ]); | |
if(sb.length()%76==0) | |
sb.append('\n'); | |
index = temp & 63 ; | |
sb.append(base64Map[ index ]); | |
if(sb.length()%76==0) | |
sb.append('\n'); | |
} | |
sb.append(padder); // Add the remaining one or two bytes | |
return sb.toString(); | |
} | |
public static String decode(String s) throws Exception | |
{ | |
byte buf[] = decodeToByteArray(s) ; | |
return new String(buf,"UTF-8") ; | |
} | |
public static byte[] decodeToByteArray(String s) throws Exception | |
{ | |
//byte hold[]; | |
if( s.length() == 0 ) return null ; | |
byte buf[] = s.getBytes("iso-8859-1") ; | |
byte debuf[] = new byte[buf.length*3/4] ; | |
byte tempBuf[]=new byte[4] ; | |
int index=0; | |
int index1=0; | |
int temp; | |
//int count=0; | |
//int count1=0; | |
// Decode to byte array | |
for(int i=0; i<buf.length;i++) | |
{ | |
if(buf[i]>=65 && buf[i]<91) | |
tempBuf[index++]=(byte)(buf[i]-65); | |
else if(buf[i]>=97 && buf[i]<123) | |
tempBuf[index++]=(byte)(buf[i]-71); | |
else if(buf[i]>=48 && buf[i]<58) | |
tempBuf[index++]=(byte)(buf[i]+4); | |
else if(buf[i]=='+') | |
tempBuf[index++]=62; | |
else if(buf[i]=='/') | |
tempBuf[index++]=63; | |
else if(buf[i]=='=') | |
{ | |
tempBuf[index++]=0; | |
//count1++; | |
} | |
// Discard line breaks and other non-significant characters | |
else | |
{ | |
if(buf[i]=='\n' || buf[i]=='\r' || buf[i]==' ' || buf[i]=='\t') | |
continue; | |
throw new RuntimeException("Illegal character found in encoded string!"); | |
} | |
if(index==4) | |
{ | |
temp=((tempBuf[0]<<18)) | (( tempBuf[1] <<12)) | ((tempBuf[2]<<6)) | (tempBuf[3]) ; | |
debuf[index1++]=(byte)(temp>>16) ; | |
debuf[index1++]=(byte)((temp>>8)&255) ; | |
debuf[index1++]=(byte)(temp&255) ; | |
//count+=3; | |
index=0; | |
} | |
} | |
//hold = new byte[count-count1]; | |
//System.arraycopy(debuf,0,hold,0,count-count1); //trim to size | |
//return hold; | |
return debuf; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment